CS333

Mobile Development


Ilya Loshkarev
loshkarev.i@gmail.com

Initialization

Structure Initialization


							struct Point {
								var x = 0.0, y = 0.0
							}
							struct Size {
								var width = 0.0, height = 0.0
							}
							let p = Point(x: 1.0, y: 1.0)
						

Structures have default memberwise initializers

Class Initialization


							class Rect {
								var origin = Point()
								var size = Size()
								init() {}
								init(origin: Point, size: Size) {
									self.origin = origin
									self.size = size
								}
							}
						

Classes don't have default memberwise initialisers

Two Kinds of Initializers


								init(origin: Point, size: Size) { // designated init
									self.origin = origin
									self.size = size
								}
						

Designated initializer fully initializes all proprties of the class


							convenience init(center: Point, size: Size) {
								let originX = center.x - (size.width / 2)
								let originY = center.y - (size.height / 2)
								self.init(origin: Point(x: originX, y: originY), size: size)
							}
						

Convenience initializer covers specific use case
of initialization parameters

Rules of Class Initialization

  • Any designated initializer must call a designated initializer
    from its superclass
  • Any convenience initializer must call another initializer
    from the same class
  • Any convenience initializer must ultimately call
    a designated initializer

Initializer Delegation


							class TextBox: Rect {
								var text: String = ""
								init(text: String, origin: Point, size: Size) { //designated init
									super.init(origin: origin, size: size)
									self.text = text;
								}
								convenience init(text: String, center: Point, size: Size) {
									let originX = center.x - (size.width / 2)
									let originY = center.y - (size.height / 2)
									self.init(text: text, origin: Point(x: originX, y: originY),
										size: size)
								}
							}
						

designated delegate up

convenience delegate across

Initializer Inheritance


							class TextBox: Rect {
								var text: String = ""
								convenience init(text: String, origin: Point, size: Size) {
									self.init(origin: origin, size: size)
									self.text = text
								}
							}
							var t = TextBox()
						

If no designated initializers declared in subclass
it inherits designated initializers of its superclass

Required Initializers


							class Rect {
								required init(){}
							}
							class TextBox {
								required init(){
									super.init()
								}
							}
							

Required initializers must be implemented as
required or final

Failable Initialization


							class TextBox: Rect {
								init? (text: String){
									if text.characters.count == 0 { return nil }
									super.init()
								}
							}
						

Failiable initializers return an optional

Protocols

Protocol Rquirements


							protocol IntContainer {
								var count: UInt { get }
								subscript(index: Int) -> Int { get }
								mutating func append(item: Int)
							}
            

Protocol lists methods and properties
required for implementation

Adopting a Protocol


							class IntStackClass: IntContainer {
								let elements: [Int]
								var count {
									return elements.count
								}
								subscript(index: Int) -> Int {
									return elements[index]
								}
								func append(item: Int) {
									elements.append(item)
								}
							}
            

Structures and classes that adopt a protocol
must implement all of the required members

Checking for Conformance


							if someObject is IntContainer {
								print((someObject as! IntContainer).count)
							}
							// binding is always a better solution
							if let container = someObject as? IntContainer {
								print(container.count)
							}
						

is and as can be used with protocols

Protocol as Type


							func createContainer(ofSize size: UInt,
								fillWith value: Int) -> IntContainer
							{
								// create some value conforming to IntContainer
							}
							let container = createContainer(ofSize: 10, fillwith:0)
							let conatiners: [IntContainer]
						

Any value of a type that adopts required protocol
can be assigned to the variable of protocol type

You can requre multiple protocol conformance by using protocol<someProtocol, anotherProtocol>

Extensions

Extension Properties


							extension Double {
							    var km: Double { return self * 1_000.0 }
							    var  m: Double { return self }
							    var cm: Double { return self / 100.0 }
							    var mm: Double { return self / 1_000.0 }
							    var ft: Double { return self / 3.28084 }
							}
							let oneInch = 25.4.mm
						

Extensions can add new functionality to a type
but they cannot override existing functionality

Extensions cannot add stored properties

Extension Methods


							extension Int {
								func times(do: () -> Void) {
									for _ in 0..<self {
											task()
									}
								}
							}

							3.times(do: { print("Hello! ") })
						

The new functionality will be availiable
on all existing instaces of a type

Extension for Protocol Adoption


							protocol TextRepresentable {
								var description: String { get }
							}
							extension Int: TextRepresentable {
								var description: String {
									return "Integer: \(self)"
								}
							}
							var i: TextRepresentable
							i = 1
            

All existing instances of a type automatically adopt and conform to a protocol

Protocol Extension


							extension TextRepresentable {
								var description: String { // default implementation
									return "I am \(self)!"
								}
								func printMe() {
									print(self.description)
								}
							}
							extention Double: TextRepresentable {}
            

Type should explicitly adopt a protocol


							3.14.printMe() // "I am 3.14!"
						

If no implementation declared in a conforming type
default one is used

Adding Constraints


							extension CollectionType where Generator.Element: TextRepresentable {
								var description: String {
									let itemsAsText = self.map { $0.description }
									return "[" + itemsAsText.joinWithSeparator(", ") + "]"
								}
							}
							var numbers = [3.14, 2.71, 1.8]
							print(numbers.description)
            

Enumerations

Enumeration Syntax


							enum Compass: Character {
								case South = "S"
								case North = "N"
								case East = "E"
								case West = "W"
							}
						

Raw value of enumeration can be integer,
floating point number, string or character


							print(Compass.South.rawValue)
						

Raw Value Initializer


							var south = Compass(rawValue: "S")
						

Raw value initalizer returns an optional

Associated Values


							enum Barcode {
							    case UPCA(Int, Int, Int, Int)
							    case QRCode(String)
							}
						

Enumerations can store associated values of any given type


							var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)»

							switch productBarcode {
							case let .UPCA(numberSystem, manufacturer, product, check):
							    print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
							case let .QRCode(productCode):
							    print("QR code: \(productCode).")
							}
						

Properties and Methods


							enum Compass {
								var opposite: Compass {
									// return opposite direction
								}
							}
						

Enumerations can store properties and methods

Enumerations are value types

Recursive Enumerations


							indirect enum ArithmeticExpression {
								case Number(Int)
								case Addition(ArithmeticExpression, ArithmeticExpression)
							}
						

Enumeration can refer itself in its declaration
with indirect


								let five = ArithmeticExpression.Number(5)
								let four = ArithmeticExpression.Number(4)
								let sum = ArithmeticExpression.Addition(five, four)
						

Standart Library

Bridging to Obective-C

  • String
  • Array
  • Dictionary
  • Set
  • NSString
  • NSArray
  • NSDictionary
  • NSSet

Global functions and interfaces from NSFoundation
are availiable in Swift

String Views


							let flag = "🇷🇺"
							print(flag.characters.count)	// Charcter View
							// Prints "1"
							print(flag.unicodeScalars.count) // Unicode View
							// Prints "2"
							print(flag.utf16.count)		// UTF-16 View
							// Prints "4"
							print(flag.utf8.count)		// UTF-8 View
							// Prints "8"
						

Each view has its own indices

String Index


							let start = str.startIndex
							let end = str.endIndex
							let range = start.successor()..<end.advancedBy(-2)
							str.replaceRange(range, with: " swift ")
						

Array


							var doubles: [Double] = []
							var emptyFloats: Array = Array()
							doubles.append(contentsOf: [3.0, 2.0, 1.0])
							doubles += [0.0, -1.0]
							var index = doubles.index(of: 2.0)
							for number in doubles {
								print("\(number)")
							}
						

Dictionary

Set

Related Resources

Swift-logo