SWIFT 2
JORIS TIMMERMAN
INTRODUCTION TO
CONTENTS
• Syntax basics
• Optionals
• Functions & Closures
• Classes
• Structs
• Enums
• Protocols
• Generics
• Extensions
• Error-Handling
THE
BASICS
VARIABLES & CONSTANTS
BASICS
//Variable	
var	myString:String	=	"This	is	my	string."	
//constant	
let	someConstant:Int	=	40
VARIABLES & CONSTANTS
BASICS
//Variable	
var	myString	=	"This	is	my	string."	//String	
//constant	
let	someConstant	=	40	//	Int
VARIABLES & CONSTANTS
BASICS
//Variable	
var	myString	=	"This	is	my	string."	//String	
//constant	
let	someConstant	=	40.0	//	Double
NAMING
BASICS
//	unicode	naming	
let	π	=	3.1415	
let	 	=	“That’s	Chinese	for	me"	
let	🐶🐮	=	"woof	moo"	
//	reserved	keywords	
var	`var`	=	"var"
ARRAYS
BASICS
• Type between [ & ]:
• let stringArray: [String] = …
• empty array:
• let emptyStringArray = [String]()
IF + LOOPS
let succeeded = true
if succeeded {
print("YES!")
} else {
print("NOOOOOOOOO!")
}
BASICS
let testNumbers = [1,2,7,9]
for number in testNumbers {
//do something with number
}
let timesToSpin = 5
//for var i : Int = 0 ; i < timesToSpin ; i++
for i:Int in 0 ..< timesToSpin {
print("Spinned (i + 1) times!")
}
RANGE OPERATORS
BASICS
• Closed range: a...b: range from a to b (including a & b)
for counter in 1...5 {
print("(counter) x 5 = (counter * 5)”)
//1 x 5 = 5
//…
//5 x 5 = 25
}
• Half-closed range: a ..< b: range from a to b (without b)
for counter in 1..<5 {
print("(counter) x 5 = (counter * 5)”)
//1 x 5 = 5
//…
//4 x 5 = 20
}
OPTIONALS
OPTIONALS
• In situations where variable can be nil
• Recognizability
• ?: can nil
• !: certain it has a value
• Optional variable has 2 possible states:
• has a value; x
• no value; nil
EXAMPLE
OPTIONALS
let image:UIImage? = UIImage(named: “picto_warning”)
//“picto_warning” exists; image has a value
print("Size of the pictogram: (image!.size)”)
EXAMPLE
OPTIONALS
let image:UIImage? = UIImage(named: "picto_warning")
///“picto_warning” does NOT exist; image = nil
print("Size of the pictogram: (image!.size)”)
EXC_BAD_ACCESS
UNWRAPPING
OPTIONALS
if let image:UIImage = UIImage(named: "picto_warning") {
//image certainly has a value
print("Size of the pictogram: (image.size)”)
}
let numberOfPicturesLoaded = 5
if let warningIcon:UIImage = UIImage(named: “picto_warning”),
errorIcon:UIImage = UIImage(named: “picto_error”)
where numberOfPicturesLoaded == 5
{
//warningIcon && errorIcon have both a value and
numberOfPicturesLoaded is 5
}
OPTIONAL CHAINING
OPTIONALS
• graceful failing when part of the chain is nil
var label:UILabel?
let someCondition = true
if someCondition == true {
label = UILabel()
label!.text = "Hello world!"
}
print(label?.text?.capitalizedString)
// Optional(“HELLO WORLD”)
OPTIONAL CHAINING
OPTIONALS
var label:UILabel?
let someCondition = true
if someCondition == true {
label = UILabel()
//label!.text = "Hello world!"
}
print(label?.text?.capitalizedString)
// nil
• graceful failing when part of the chain is nil
OPTIONAL CHAINING
OPTIONALS
• graceful failing when part of the chain is nil
var label:UILabel?
let someCondition = false
if someCondition == true {
label = UILabel()
label!.text = "Hello world!"
}
print(label?.text?.capitalizedString)
// nil
FUNCTIONS
&
CLOSURES
FUNCTIONS
FUNCTIONS & CLOSURES
• keyword: func	
• parameters: 	
• paramName:Type	
• separated by commas
• return value: ->	Type	
• Usage:
func sayHello(name: String) -> String {
return "Hello (name)"
}
let greeting = sayHello("John")
TUPLES
FUNCTIONS & CLOSURES
• Returning multiple values
• can be queried by name or index


func processNumbers(numbers: Int...) -> (sum:Int, average:Double) {
var sum = 0
for number in numbers {
sum += number
}
return (sum:sum, average:Double(sum)/Double(numbers.count))
}
let result = processNumbers(2,3)
print("Som is: (result.sum), gemiddelde is: (result.average)")
CLOSURES
FUNCTIONS & CLOSURES
• Block of code that can be executed later
• has access to variables & functions available in the scope when it
is created
• even when the closure is executed in a different scope
let testClosure = { (param:String) -> String in
return "Some param is (param)"
}
let fullString = testClosure(“Hello")
print(fullString) // "Some param is Hello"
CLOSURES
FUNCTIONS & CLOSURES
• If parameter type is known, you can drop parameter type & return
type
let numbers = [1,2,3]
let sortedNumbers = numbers.sort { (v1:Int, v2:Int) -> Bool in
return v1 < v2
}
CLOSURES
FUNCTIONS & CLOSURES
• If parameter type is known, you can drop parameter type & return
type
let numbers = [1,2,3]
let sortedNumbers = numbers.sort { $0 > $1 }
CLASSES
CLASSES
• keyword: class	
• inheritance & implementations: 

class	SomeThing	:	BaseClass,	Protocol1,	Protocol2	
• stored properties: same	like	variable	definitions	
var fileName:String?
• constructor: init()	
• dealloc: deinit()	
• accessors: internal	(default)	&	private	
• internal: in the module
• private: just within class scope
• public: exists too, when access is needed outside module scope (eg. libraries)
COMPUTED PROPERTIES
CLASSES
• In contrast to stored properties
• don’t store a value (directly)
• getter and/or setter closure
class Frame {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newValue) {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
COMPUTED PROPERTIES
CLASSES
• In contrast to stored properties
• don’t store a value (directly)
• getter and/or setter closure
class Frame {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
}
}
READ-ONLY
COMPUTED PROPERTIES
CLASSES
• In contrast to stored properties
• don’t store a value (directly)
• getter and/or setter closure
class Frame {
var origin = Point()
var size = Size()
var center: Point {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
}
READ-ONLY
PROPERTIES
CLASSES
• property observers:
• willSet(newValue): will be executed before value changes
• didSet(oldValue): executed after value change
• lazy stored properties
• value calculated at first usage
• keyword: lazy
CLASS LEVEL VARIABLES & FUNCTIONS
CLASSES
• keyword: static	
• for stored properties
• final; not overridable in subclass
• keyword: class	
• functions & calculated properties
• overridable

class var overrides a 'final' class var
CLASS LEVEL VARIABLES & FUNCTIONS
CLASSES
class SomeClass {
static var someValueProperty = "Some value."
class var computedHeigth: Float {
return 27
}
static var computedStrength: Float {
return 0.993
}
}
class AnotherClass:SomeClass {
override class var computedHeigth:Float {
return 123
}
override static var computedStrength:Float {
return 0.02
}
}
INITIALIZERS
CLASSES
• Keyword: init
init() { }
init(arg:AnyObject) { }
• required initializer
• initializer that has to be implemented
• every subclass has to override it
• convenience initializer
• utility, handy
• must call a required initializer
INITIALIZERS
CLASSES
• Failable initializers
init?(string:String) { }
• Fail initialization when arguments are illegal
• bv NSURL
let url:NSSURL? = NSURL(string:”http://google.com?q=http://cozmos.be”)
//url : nil (illegale url string)
• nil returned when initialization fails
STRUCTS
STRUCTS
• Holds values
struct Location {
let latitude: Double
let longitude: Double
}
• Adds functionality to these values
struct Location {
var latitude: Double
var longitude: Double
static var centerLocation:Location {
//automagic initializer!
return Location(latitude: 0, longitude: 0)
}
mutating func add1Degree() {
self.longitude += 1
self.latitude += 1
}
func getDistanceToLocation(loc:Location) -> Float {
//...
}
}
STRUCTS
• Can do what classes can do too:
• implementing protocols
• Properties
• Functions
• Initializers
• Subscripts
STRUCTS
• Cannot do what classes can do:
• Inheritance
• type casting at runtime
• reference counting, passing a struct copies it
ENUMS
ENUMS
• keyword: enum	
• Lijst of possible values
enum SocialFriendType{
case Acquainted
case Friend
case Family
case Coworker
case Other
}
ENUMS
• keyword: enum	
• Lijst of possible values
enum SocialFriendType : String {
case Acquainted = "a"
case Friend(name:String) = "fr"
case Family = "fa"
case Coworker = "col"
case Other = "n/a"
init() {
self = .Friend
}
var isClose : Bool {
return self == .Friend || self == .Family
}
}
let type:SocialFriendType = .Acquainted
print(type.rawValue) //a
PROTOCOLS
PROTOCOLS
• keyword: protocol
• Blueprint composed of methods & properties
• Implementable by classes, structs and enums
PROTOCOLS
• Extendable, a protocol can ‘inherit’ from another protocol


protocol Animal {
var species: String { get }
var canFly: Bool { get }
}
protocol Flyable {
var airspeed: Double { get }
var wingSpan: Double { get }
}
protocol Bird : Animal, Flyable {
}
EXTENDING PROTOCOLS
PROTOCOLS
• Default values
extension Animal where Self : FlyingAnimal {
var canFly: Bool { return true }
}
GENERICS
GENERICS
• Obj-C problem: NSArray can hold anything
• + flexible
• - not type-safe, no garanty API returns documented values
• Swift Solution: typed collections [String], [Int], …
• + Type-safe, certainty
• - code duplication
GENERICS
• Required: method that will loop over these arrays and doStuff()
let strings = ["1", "2", "3", "4"]
let ints = [1,2,3,4]
let doubles = [1.1, 1.2, 1.3, 1.4]
func doStuffWithStringArray(strings: [String]) {
for s in strings {
doStuff(s)
}
}
doStuffWithStringArray(strings)
func doStuffWithIntArray(numbers: [Int]) {
for i in numbers {
doStuff(i)
}
}
doStuffWithIntArray(ints)
func doStuffWithDoubleArray(doubles: [Double]) {
for d in doubles {
doStuff(d)
}
}
doStuffWithDoubleArray(doubles)
MAGIC!
GENERICS
• Solution: Generics
let strings = ["1", "2", "3", "4"]
let ints = [1,2,3,4]
let doubles = [1.1, 1.2, 1.3, 1.4]
func doStuffWithAnyArray<T>(array:[T]) {
for item in array {
doStuff(item)
}
}
doStuffWithAnyArray(strings)
doStuffWithAnyArray(ints)
doStuffWithAnyArray(doubles)
MAGIC PLACEHOLDER
GENERICS
• Solution: Generics
let strings = ["1", "2", "3", "4"]
let ints = [1,2,3,4]
let doubles = [1.1, 1.2, 1.3, 1.4]
func doStuffWithAnyArray<Cozmos>(array:[Cozmos]) {
for item in array {
doStuff(item)
}
}
doStuffWithAnyArray(strings)
doStuffWithAnyArray(ints)
doStuffWithAnyArray(doubles)
GENERICS
• T = Placeholder
• Type determined when function is called
let strings = ["1", "2", "3", "4"]
func doStuffWithAnyArray<T>(array:[T]) {
for item in array {
doStuff(item)
}
}
doStuffWithAnyArray(strings)
• T becomes String
• Works for functions, classes, enums & structs
REQUIREMENTS
GENERICS
• Requirements:

Elements should be comparable

Elementen in both sequences should be the same type

func hasCommonItems <T: SequenceType, U: SequenceType>
(left: T, _ right: U) -> Bool {
for leftItem in left {
for rightItem in right {
if leftItem == rightItem {
return true
}
}
}
return false
}
hasCommonItems([7, 42, 69], [42])
REQUIREMENTS
GENERICS
• Requirements:

Elements should be comparable

Elementen in both sequences should be the same type

func hasCommonItems <T: SequenceType, U: SequenceType
where T.Generator.Element: Equatable,
U.Generator.Element: Equatable,
T.Generator.Element == U.Generator.Element>
(left: T, _ right: U) -> Bool {
for leftItem in left {
for rightItem in right {
if leftItem == rightItem {
return true
}
}
}
return false
}
hasCommonItems([7, 42, 69], [42])
EXTENSIONS
EXTENSIONS
• keyword: extension
• extensions add functionality to classes, structs, protocols & enums
• computed properties
• (class) methods
• new initializers
• …
EXTENSIONS
• Extending Swift library
extension Double {
var m: Double { return self }
var ft: Double { return self / 3.28084 }
}
let distanceInFt = 20.0.ft //6.0959998
EXTENSIONS
• Making an existing type conform to a protocol
protocol MapDrawable {
var location:CLLocationCoordinate2D { get }
}
class House : NSManagedObject {
@NSManaged var identifier:Int = 0
@NSManaged var hasGarden:Bool = false
@NSManaged var numberOfFaces:Int = 4
}
extension House : MapDrawable {
var location:CLLocationCoordinate2D {
return CLLocationCoordinate2DMake(4.2564, 3.27654)
}
}
MUTATING METHODS
EXTENSIONS
• Methods (in an extension) that can change the instance (self)
• keyword: mutating
• for enums & structs

extension Int {
mutating func squared() {
self = self * self
}
}
var value:Int = 2
value.squared()
print("Value is (value)”) //Value is 4
ERROR-
HANDLING
ERRORHANDLING
• Catching errors
• throwing function: function marked with ‘throws’


func performPrintTask() throws -> String { }
• Error handling: do, try, catch
func printSomething() {
do {
let response = try performPrintTask()
handleResponse(response)
} catch PrinterError.Unreachable {
print("Unreachable")
} catch PrinterError.InsufficientInkt {
print("Need Ink")
} catch PrinterError.BecausePrinters {
print("Sigh")
} catch {
print("No idea")
}
}
ERRORHANDLING
• Errors: need to implement protocol ErrorType
enum PrinterError: ErrorType {
case Unreachable
case InsufficientInkt(c:Double, m:Double, y:Double, k:Double)
case BecausePrinters
}
throw PrinterError.BecausePrinters
ERRORHANDLING
• Converting errors to optional values
let response:String? = try? performPrintTask()
• When error occurs: response = nil
ERRORHANDLING
• If you are absolutely sure no error can happen
let response:String = try! performPrintTask()
• When an error is thrown: crash
ERRORHANDLING
• keyword defer
• block of code that is executed before a function returns
• before return statement
• before throw
• Can also be used in methods that don’t throw errors
Introduction to Swift 2

Introduction to Swift 2

  • 1.
  • 2.
    CONTENTS • Syntax basics •Optionals • Functions & Closures • Classes • Structs • Enums • Protocols • Generics • Extensions • Error-Handling
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
    ARRAYS BASICS • Type between[ & ]: • let stringArray: [String] = … • empty array: • let emptyStringArray = [String]()
  • 9.
    IF + LOOPS letsucceeded = true if succeeded { print("YES!") } else { print("NOOOOOOOOO!") } BASICS let testNumbers = [1,2,7,9] for number in testNumbers { //do something with number } let timesToSpin = 5 //for var i : Int = 0 ; i < timesToSpin ; i++ for i:Int in 0 ..< timesToSpin { print("Spinned (i + 1) times!") }
  • 10.
    RANGE OPERATORS BASICS • Closedrange: a...b: range from a to b (including a & b) for counter in 1...5 { print("(counter) x 5 = (counter * 5)”) //1 x 5 = 5 //… //5 x 5 = 25 } • Half-closed range: a ..< b: range from a to b (without b) for counter in 1..<5 { print("(counter) x 5 = (counter * 5)”) //1 x 5 = 5 //… //4 x 5 = 20 }
  • 11.
  • 12.
    OPTIONALS • In situationswhere variable can be nil • Recognizability • ?: can nil • !: certain it has a value • Optional variable has 2 possible states: • has a value; x • no value; nil
  • 13.
    EXAMPLE OPTIONALS let image:UIImage? =UIImage(named: “picto_warning”) //“picto_warning” exists; image has a value print("Size of the pictogram: (image!.size)”)
  • 14.
    EXAMPLE OPTIONALS let image:UIImage? =UIImage(named: "picto_warning") ///“picto_warning” does NOT exist; image = nil print("Size of the pictogram: (image!.size)”) EXC_BAD_ACCESS
  • 15.
    UNWRAPPING OPTIONALS if let image:UIImage= UIImage(named: "picto_warning") { //image certainly has a value print("Size of the pictogram: (image.size)”) } let numberOfPicturesLoaded = 5 if let warningIcon:UIImage = UIImage(named: “picto_warning”), errorIcon:UIImage = UIImage(named: “picto_error”) where numberOfPicturesLoaded == 5 { //warningIcon && errorIcon have both a value and numberOfPicturesLoaded is 5 }
  • 16.
    OPTIONAL CHAINING OPTIONALS • gracefulfailing when part of the chain is nil var label:UILabel? let someCondition = true if someCondition == true { label = UILabel() label!.text = "Hello world!" } print(label?.text?.capitalizedString) // Optional(“HELLO WORLD”)
  • 17.
    OPTIONAL CHAINING OPTIONALS var label:UILabel? letsomeCondition = true if someCondition == true { label = UILabel() //label!.text = "Hello world!" } print(label?.text?.capitalizedString) // nil • graceful failing when part of the chain is nil
  • 18.
    OPTIONAL CHAINING OPTIONALS • gracefulfailing when part of the chain is nil var label:UILabel? let someCondition = false if someCondition == true { label = UILabel() label!.text = "Hello world!" } print(label?.text?.capitalizedString) // nil
  • 19.
  • 20.
    FUNCTIONS FUNCTIONS & CLOSURES •keyword: func • parameters: • paramName:Type • separated by commas • return value: -> Type • Usage: func sayHello(name: String) -> String { return "Hello (name)" } let greeting = sayHello("John")
  • 21.
    TUPLES FUNCTIONS & CLOSURES •Returning multiple values • can be queried by name or index 
 func processNumbers(numbers: Int...) -> (sum:Int, average:Double) { var sum = 0 for number in numbers { sum += number } return (sum:sum, average:Double(sum)/Double(numbers.count)) } let result = processNumbers(2,3) print("Som is: (result.sum), gemiddelde is: (result.average)")
  • 22.
    CLOSURES FUNCTIONS & CLOSURES •Block of code that can be executed later • has access to variables & functions available in the scope when it is created • even when the closure is executed in a different scope let testClosure = { (param:String) -> String in return "Some param is (param)" } let fullString = testClosure(“Hello") print(fullString) // "Some param is Hello"
  • 23.
    CLOSURES FUNCTIONS & CLOSURES •If parameter type is known, you can drop parameter type & return type let numbers = [1,2,3] let sortedNumbers = numbers.sort { (v1:Int, v2:Int) -> Bool in return v1 < v2 }
  • 24.
    CLOSURES FUNCTIONS & CLOSURES •If parameter type is known, you can drop parameter type & return type let numbers = [1,2,3] let sortedNumbers = numbers.sort { $0 > $1 }
  • 25.
  • 26.
    CLASSES • keyword: class •inheritance & implementations: 
 class SomeThing : BaseClass, Protocol1, Protocol2 • stored properties: same like variable definitions var fileName:String? • constructor: init() • dealloc: deinit() • accessors: internal (default) & private • internal: in the module • private: just within class scope • public: exists too, when access is needed outside module scope (eg. libraries)
  • 27.
    COMPUTED PROPERTIES CLASSES • Incontrast to stored properties • don’t store a value (directly) • getter and/or setter closure class Frame { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newValue) { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } }
  • 28.
    COMPUTED PROPERTIES CLASSES • Incontrast to stored properties • don’t store a value (directly) • getter and/or setter closure class Frame { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } } } READ-ONLY
  • 29.
    COMPUTED PROPERTIES CLASSES • Incontrast to stored properties • don’t store a value (directly) • getter and/or setter closure class Frame { var origin = Point() var size = Size() var center: Point { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } } READ-ONLY
  • 30.
    PROPERTIES CLASSES • property observers: •willSet(newValue): will be executed before value changes • didSet(oldValue): executed after value change • lazy stored properties • value calculated at first usage • keyword: lazy
  • 31.
    CLASS LEVEL VARIABLES& FUNCTIONS CLASSES • keyword: static • for stored properties • final; not overridable in subclass • keyword: class • functions & calculated properties • overridable

  • 32.
    class var overridesa 'final' class var CLASS LEVEL VARIABLES & FUNCTIONS CLASSES class SomeClass { static var someValueProperty = "Some value." class var computedHeigth: Float { return 27 } static var computedStrength: Float { return 0.993 } } class AnotherClass:SomeClass { override class var computedHeigth:Float { return 123 } override static var computedStrength:Float { return 0.02 } }
  • 33.
    INITIALIZERS CLASSES • Keyword: init init(){ } init(arg:AnyObject) { } • required initializer • initializer that has to be implemented • every subclass has to override it • convenience initializer • utility, handy • must call a required initializer
  • 34.
    INITIALIZERS CLASSES • Failable initializers init?(string:String){ } • Fail initialization when arguments are illegal • bv NSURL let url:NSSURL? = NSURL(string:”http://google.com?q=http://cozmos.be”) //url : nil (illegale url string) • nil returned when initialization fails
  • 35.
  • 36.
    STRUCTS • Holds values structLocation { let latitude: Double let longitude: Double } • Adds functionality to these values struct Location { var latitude: Double var longitude: Double static var centerLocation:Location { //automagic initializer! return Location(latitude: 0, longitude: 0) } mutating func add1Degree() { self.longitude += 1 self.latitude += 1 } func getDistanceToLocation(loc:Location) -> Float { //... } }
  • 37.
    STRUCTS • Can dowhat classes can do too: • implementing protocols • Properties • Functions • Initializers • Subscripts
  • 38.
    STRUCTS • Cannot dowhat classes can do: • Inheritance • type casting at runtime • reference counting, passing a struct copies it
  • 39.
  • 40.
    ENUMS • keyword: enum •Lijst of possible values enum SocialFriendType{ case Acquainted case Friend case Family case Coworker case Other }
  • 41.
    ENUMS • keyword: enum •Lijst of possible values enum SocialFriendType : String { case Acquainted = "a" case Friend(name:String) = "fr" case Family = "fa" case Coworker = "col" case Other = "n/a" init() { self = .Friend } var isClose : Bool { return self == .Friend || self == .Family } } let type:SocialFriendType = .Acquainted print(type.rawValue) //a
  • 42.
  • 43.
    PROTOCOLS • keyword: protocol •Blueprint composed of methods & properties • Implementable by classes, structs and enums
  • 44.
    PROTOCOLS • Extendable, aprotocol can ‘inherit’ from another protocol 
 protocol Animal { var species: String { get } var canFly: Bool { get } } protocol Flyable { var airspeed: Double { get } var wingSpan: Double { get } } protocol Bird : Animal, Flyable { }
  • 45.
    EXTENDING PROTOCOLS PROTOCOLS • Defaultvalues extension Animal where Self : FlyingAnimal { var canFly: Bool { return true } }
  • 46.
  • 47.
    GENERICS • Obj-C problem:NSArray can hold anything • + flexible • - not type-safe, no garanty API returns documented values • Swift Solution: typed collections [String], [Int], … • + Type-safe, certainty • - code duplication
  • 48.
    GENERICS • Required: methodthat will loop over these arrays and doStuff() let strings = ["1", "2", "3", "4"] let ints = [1,2,3,4] let doubles = [1.1, 1.2, 1.3, 1.4] func doStuffWithStringArray(strings: [String]) { for s in strings { doStuff(s) } } doStuffWithStringArray(strings) func doStuffWithIntArray(numbers: [Int]) { for i in numbers { doStuff(i) } } doStuffWithIntArray(ints) func doStuffWithDoubleArray(doubles: [Double]) { for d in doubles { doStuff(d) } } doStuffWithDoubleArray(doubles)
  • 49.
    MAGIC! GENERICS • Solution: Generics letstrings = ["1", "2", "3", "4"] let ints = [1,2,3,4] let doubles = [1.1, 1.2, 1.3, 1.4] func doStuffWithAnyArray<T>(array:[T]) { for item in array { doStuff(item) } } doStuffWithAnyArray(strings) doStuffWithAnyArray(ints) doStuffWithAnyArray(doubles)
  • 50.
    MAGIC PLACEHOLDER GENERICS • Solution:Generics let strings = ["1", "2", "3", "4"] let ints = [1,2,3,4] let doubles = [1.1, 1.2, 1.3, 1.4] func doStuffWithAnyArray<Cozmos>(array:[Cozmos]) { for item in array { doStuff(item) } } doStuffWithAnyArray(strings) doStuffWithAnyArray(ints) doStuffWithAnyArray(doubles)
  • 51.
    GENERICS • T =Placeholder • Type determined when function is called let strings = ["1", "2", "3", "4"] func doStuffWithAnyArray<T>(array:[T]) { for item in array { doStuff(item) } } doStuffWithAnyArray(strings) • T becomes String • Works for functions, classes, enums & structs
  • 52.
    REQUIREMENTS GENERICS • Requirements:
 Elements shouldbe comparable
 Elementen in both sequences should be the same type
 func hasCommonItems <T: SequenceType, U: SequenceType> (left: T, _ right: U) -> Bool { for leftItem in left { for rightItem in right { if leftItem == rightItem { return true } } } return false } hasCommonItems([7, 42, 69], [42])
  • 53.
    REQUIREMENTS GENERICS • Requirements:
 Elements shouldbe comparable
 Elementen in both sequences should be the same type
 func hasCommonItems <T: SequenceType, U: SequenceType where T.Generator.Element: Equatable, U.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (left: T, _ right: U) -> Bool { for leftItem in left { for rightItem in right { if leftItem == rightItem { return true } } } return false } hasCommonItems([7, 42, 69], [42])
  • 54.
  • 55.
    EXTENSIONS • keyword: extension •extensions add functionality to classes, structs, protocols & enums • computed properties • (class) methods • new initializers • …
  • 56.
    EXTENSIONS • Extending Swiftlibrary extension Double { var m: Double { return self } var ft: Double { return self / 3.28084 } } let distanceInFt = 20.0.ft //6.0959998
  • 57.
    EXTENSIONS • Making anexisting type conform to a protocol protocol MapDrawable { var location:CLLocationCoordinate2D { get } } class House : NSManagedObject { @NSManaged var identifier:Int = 0 @NSManaged var hasGarden:Bool = false @NSManaged var numberOfFaces:Int = 4 } extension House : MapDrawable { var location:CLLocationCoordinate2D { return CLLocationCoordinate2DMake(4.2564, 3.27654) } }
  • 58.
    MUTATING METHODS EXTENSIONS • Methods(in an extension) that can change the instance (self) • keyword: mutating • for enums & structs
 extension Int { mutating func squared() { self = self * self } } var value:Int = 2 value.squared() print("Value is (value)”) //Value is 4
  • 59.
  • 60.
    ERRORHANDLING • Catching errors •throwing function: function marked with ‘throws’ 
 func performPrintTask() throws -> String { } • Error handling: do, try, catch func printSomething() { do { let response = try performPrintTask() handleResponse(response) } catch PrinterError.Unreachable { print("Unreachable") } catch PrinterError.InsufficientInkt { print("Need Ink") } catch PrinterError.BecausePrinters { print("Sigh") } catch { print("No idea") } }
  • 61.
    ERRORHANDLING • Errors: needto implement protocol ErrorType enum PrinterError: ErrorType { case Unreachable case InsufficientInkt(c:Double, m:Double, y:Double, k:Double) case BecausePrinters } throw PrinterError.BecausePrinters
  • 62.
    ERRORHANDLING • Converting errorsto optional values let response:String? = try? performPrintTask() • When error occurs: response = nil
  • 63.
    ERRORHANDLING • If youare absolutely sure no error can happen let response:String = try! performPrintTask() • When an error is thrown: crash
  • 64.
    ERRORHANDLING • keyword defer •block of code that is executed before a function returns • before return statement • before throw • Can also be used in methods that don’t throw errors