swift school #2

86
Swift Школа Сергей Пронин Empatika

Upload: sergey-pronin

Post on 15-Jun-2015

319 views

Category:

Education


1 download

DESCRIPTION

Второе занятие в рамках Swift School По всем вопросам пишите на [email protected]

TRANSCRIPT

Page 1: Swift School #2

Swift Школа

Сергей Пронин Empatika

Page 2: Swift School #2

План

• Перечисления

• Generic

• Протоколы

• Optionals

Page 3: Swift School #2

Перечисления

Page 4: Swift School #2

Перечисления Enumerations

• Полноценный тип (наравне с классами)

• Обладает свойствами класса конструкторы, вычисляемые свойства, динамические методы (у объектов)

• Поддерживает расширения (extensions - категории) и протоколы (protocols)

Page 5: Swift School #2

enum Animal { // значения case Dog case Cat case Fish case Robot }

enum LazyAnimal { // Одного 'case' достаточно case Dog, Cat, Fish, Robot }

По умолчанию значениям не присваиваются Int эквиваленты

Каждое значение имеет тип своего перечисления

Page 6: Swift School #2

let pet = Animal.Dog switch pet { case .Dog: println("WOF-WOF") case .Cat: println("MEOW") case .Fish: println("???") case .Robot: println("Death to humans!") }

Page 7: Swift School #2

“Ассоциированные” значения

• Каждый объект перечисления может содержать объект другого типа в качестве соответствия

• В таком случае их типы могут быть разными

• Позволяет “ассоциировать” любую информацию

Page 8: Swift School #2

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

var productBarcode = Barcode.UPCA(1, 2, 3) productBarcode = .PDF417("ABCD")

Page 9: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

Page 10: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {

Page 11: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check):

Page 12: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")

Page 13: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code):

Page 14: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")

Page 15: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

Page 16: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

Page 17: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugar

Page 18: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugarswitch productBarcode {

Page 19: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugarswitch productBarcode {case let .UPCA(system, ident, check):

Page 20: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugarswitch productBarcode {case let .UPCA(system, ident, check): println("UPCA with value of \(system), \(ident), \(check).")

Page 21: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugarswitch productBarcode {case let .UPCA(system, ident, check): println("UPCA with value of \(system), \(ident), \(check).")case let .PDF417(code):

Page 22: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugarswitch productBarcode {case let .UPCA(system, ident, check): println("UPCA with value of \(system), \(ident), \(check).")case let .PDF417(code): println("PDF417 with value of \(code).")

Page 23: Swift School #2

Ассоциированные значения доступны в switch-case конструкции

switch productBarcode {case .UPCA(let system, let ident, let check): println("UPCA with value of \(system), \(ident), \(check).")case .PDF417(let code): println("PDF417 with value of \(code).")}

// Syntax sugarswitch productBarcode {case let .UPCA(system, ident, check): println("UPCA with value of \(system), \(ident), \(check).")case let .PDF417(code): println("PDF417 with value of \(code).")}

Page 24: Swift School #2

“Замещающие” значения

• Каждый объект перечисления может быть сопоставлен с объектом другого типа

• “Замещающие” значения не меняются (в отличие от “ассоциированных”

• Допустимые типы: Character, String, Double, Float, Int*

Page 25: Swift School #2

// для Int работает auto-increment enum Number: Int { case One = 1, Two, Three, Four, Five, Six, Seven, Eight, FortyTwo = 42 }

enum Letter: Character { case A = "a" case B = "b" case C = "c" }

let answerToTheAllQuestions = Number.FortyTwo answerToTheAllQuestions.toRaw()

let twoOnTwo = Number.fromRaw(2 * 2) twoOnTwo?.toRaw()

Page 26: Swift School #2

*// свой тип для перечислений final class CustomRawType: IntegerLiteralConvertible, Equatable { let number: Int let square: Int let cube: Int class func convertFromIntegerLiteral(value: Int) -> CustomRawType { return CustomRawType(number: value) } init(number: Int) { self.number = number self.square = number * number self.cube = number * number * number }

func == (lhs: CustomRawType, rhs: CustomRawType) -> Bool { return lhs.number == rhs.number } }

Page 27: Swift School #2

• Структура или final класс • Equatable протокол • Любой *LiteralConvertible протокол

enum Number2: CustomRawType { case One = 1 case Two = 2 case Three = 3 }

let three = Number2.Three let rawThree = three.toRaw() rawThree.cube

Page 28: Swift School #2

Generic

Page 29: Swift School #2

Generiс

• Одна из самых интересных особенностей Swift

• Повышает гибкость и переиспользуемость кода

• Swift Standard Library во многом написана с использованием Generic типов

Page 30: Swift School #2

Generic функции

Page 31: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) {

Page 32: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b

Page 33: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a

Page 34: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp

Page 35: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

Page 36: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

Page 37: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

var a_s = "a"

Page 38: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

var a_s = "a"var b_s = "a"

Page 39: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

var a_s = "a"var b_s = "a"var a_i = 1

Page 40: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

var a_s = "a"var b_s = "a"var a_i = 1var b_i = 2

Page 41: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

var a_s = "a"var b_s = "a"var a_i = 1var b_i = 2genericSwap(&a_s, &b_s)

Page 42: Swift School #2

Generic функции

func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp}

var a_s = "a"var b_s = "a"var a_i = 1var b_i = 2genericSwap(&a_s, &b_s)genericSwap(&a_i, &b_i)

Page 43: Swift School #2

Generic типы

Page 44: Swift School #2

Generic типыclass GenericStack<T> { var elements = [T]() func push(object: T) { elements.append(object) } func pop() { elements.removeLast() } func peek() -> T? { return elements.last } func isEmpty() -> Bool { return elements.isEmpty } }

Page 45: Swift School #2

Generic типыclass GenericStack<T> { var elements = [T]() func push(object: T) { elements.append(object) } func pop() { elements.removeLast() } func peek() -> T? { return elements.last } func isEmpty() -> Bool { return elements.isEmpty } }

let intStack = GenericStack<Int>() intStack.push(12) intStack.push(123) intStack.pop()

let stringStack = GenericStack<String>() stringStack.push("a") stringStack.push("ba") stringStack.pop()

Page 46: Swift School #2

Ограничения на типы

Page 47: Swift School #2

Ограничения на типыclass MyClass { }

Page 48: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }

Page 49: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }

Page 50: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }

Page 51: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

Page 52: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

Page 53: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

Page 54: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

Page 55: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

// compile error

Page 56: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

// compile error// let example = Example<Int, Double>()

Page 57: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

// compile error// let example = Example<Int, Double>()let example2 = Example<MyClass, MyClassWithProtocol>()

Page 58: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

// compile error// let example = Example<Int, Double>()let example2 = Example<MyClass, MyClassWithProtocol>()let example3 = Example<MyClass2, MyClassWithProtocol>()

Page 59: Swift School #2

Ограничения на типыclass MyClass { }protocol MyProtocol { }class MyClassWithProtocol: MyProtocol { }class MyClass2: MyClass { }class MyClass3: MyClass, MyProtocol { }

class Example<T: MyClass, U: MyProtocol> { }

// compile error// let example = Example<Int, Double>()let example2 = Example<MyClass, MyClassWithProtocol>()let example3 = Example<MyClass2, MyClassWithProtocol>()let example4 = Example<MyClass3, MyClass3>() // OK

Page 60: Swift School #2

Ассоциированные типы

protocol Stack { typealias ObjectType func push(object: ObjectType) func pop() func peek() -> ObjectType? }

ObjectType будет объявлен позже: в классе, который реализует протокол

Page 61: Swift School #2

// Stack protocol автоматически возьмёт T // в качестве типа для typealias ObjectType class AnotherGenericStack<T>: Stack { var elements = [T]() func isEmpty() -> Bool { return elements.isEmpty } func push(object: T) { elements.append(object) } func pop() { elements.removeLast() } func peek() -> T? { return elements.last } }

Page 62: Swift School #2

class IntStack: Stack { var elements = [Int]() func isEmpty() -> Bool { return elements.isEmpty } // Для не-generic типов нужно // явно объявить тип для typealias ObjectType typealias ObjectType = Int func push(object: ObjectType) { elements.append(object) } func pop() { elements.removeLast() } func peek() -> ObjectType? { return elements.last } }

Page 63: Swift School #2

Протоколы

Page 64: Swift School #2

Александр Зимин

iOS developer UX designer

[email protected]

Page 65: Swift School #2

Протоколы

Протокол - это шаблон методов и свойств, которыми будет обладать определенный класс, структура или перечисление, если решит его реализовать

Page 66: Swift School #2

Зачем нужны протоколы

Page 67: Swift School #2

Зачем нужны протоколы

1. Безопасность Протоколы гарантируют проверку на реализацию всех необходимых методов и свойств

Page 68: Swift School #2

Зачем нужны протоколы

1. Безопасность Протоколы гарантируют проверку на реализацию всех необходимых методов и свойств

2. Упрощенное использование Протоколы позволяют разработчику понять, какими свойствами обладает класс, структура или перечисление, не зная конкретный тип

Page 69: Swift School #2

protocol Vehicle {

var wheels: Int { get set } var isRequiresFuel: Bool { get } func start() -> String }

Page 70: Swift School #2

class Car: Vehicle { var wheels: Int = 4 let isRequiresFuel: Bool = true func start() -> String { return "Сar starts its journey" } }

var myCar = Car() myCar.wheels = 6 myCar.wheels // 6 myCar.isRequiresFuel // true myCar.start() // "Сar starts its journey"

Page 71: Swift School #2

class Bike: Vehicle { var wheels: Int = 2 var isRequiresFuel: Bool init(isWithFuel: Bool) { self.isRequiresFuel = isWithFuel } func start() -> String { return "Bike starts its journey" } }

var myTransport: Vehicle

myTransport = Bike(isWithFuel: false) myTransport.wheels // 2 myTransport.isRequiresFuel // false myTransport.start() // "Bike starts its journey"

myTransport = Car() myTransport.wheels // 4

Page 72: Swift School #2

protocol Togglable { mutating func toggle() var state: String { get } }

Page 73: Swift School #2

enum OnOffSwitch: Togglable { case Off, On mutating func toggle() { switch self { case Off: self = On case On: self = Off } } var state: String { get { switch self { case Off: return "Off" case On: return "On" } } } }

Page 74: Swift School #2

var switcher: Togglable = OnOffSwitch.On switcher.state // "On" switcher.toggle() switcher.state // “Off"

func getLamp() -> Togglable

var currentLamp: Togglable = getLamp() currentLamp.toggle()

Page 75: Swift School #2

Optionals

Page 76: Swift School #2

Природа Optionals

Optional тип - это на самом деле enum, который может содержать либо .None либо .Some(T)

Optionals позволяют отследить момент отсутствия значения у переменной

Page 77: Swift School #2

Опциональность в Obj-C

У NSObject (супер-класс) могло быть значение nil (NULL).

Для Int и прочих базовых типов использовались константы (к примеру NSNotFound), которые определяли какое-то значение (к примеру -1 или INT_MAX)

Page 78: Swift School #2
Page 79: Swift School #2

Обозначения

T? - опциональный тип optional type

T! - косвенно раскрывающийся опциональный тип implicitly unwrapped optional

v? - вызов цепочки от опционального типа optional chaining

v! - распаковка опционального типа unwrapping optional

Page 80: Swift School #2

enum Optional<T> : Reflectable, NilLiteralConvertible { case None case Some(T) init() init(_ some: T)

/// Haskell's fmap, which was mis-named func map<U>(f: (T) -> U) -> U? func getMirror() -> MirrorType static func convertFromNilLiteral() -> T? }

var optionalValue = Optional<Int>(5) // {Some 5} optionalValue = nil // nil optionalValue = 10 // {Some 10} optionalValue = Optional<Int>.None // nil optionalValue = Optional.Some(15) // {Some 15} optionalValue = Optional.convertFromNilLiteral() // nil

Page 81: Swift School #2

var optionalObject: AnyObject? = nil

var object: AnyObject = nil COMPILATION ERROR: Type 'AnyObject' does not conform to the protocol 'NilLiteralConvertible

Page 82: Swift School #2

Использование и базовые операции

var optionalString: String? // nil optionalString = "Content"

// Unwrapping. error if optionalString == nil optionalString! optionalString? // Optional chaining optionalString?.hasPrefix("Con") optionalString.hasPrefix("") COMPILE ERROR: String? does not have a member named “hasPrefix”

if let string = optionalString { // Safe unwrap // Use string }

Page 83: Swift School #2

Первый “?” позволяет вызвать метод если object != nil Второй “?” вызывает method(params) только если у объекта таковой реализован (respondsToSelector в obj-c) object?.method?(params)

var jsonContent: AnyObject? jsonContent?.objectForKey?("content")?.objectForKey?("info")?[5]

Page 84: Swift School #2

Косвенно раскрывающийся опциональный тип

implicitly unwrapped optionalsvar unwrappedOptionalString: String! // nil unwrappedOptionalString = "Content" // "Content"

if let str = unwrappedOptionalString { str.hasPrefix("co") // false // Work with str }

unwrappedOptionalString.hasPrefix("Co") // true

unwrappedOptionalString = nil unwrappedOptionalString?.hasPrefix("Co") // nil unwrappedOptionalString.hasPrefix("Co") RUNTIME ERROR: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

Page 85: Swift School #2

Вопросы