Advertisement
Advertisement

More Related Content

Slideshows for you(20)

Advertisement
Advertisement

Swift School #2

  1. Swift Школа Сергей Пронин Empatika
  2. План • Перечисления • Generic • Протоколы • Optionals
  3. Перечисления
  4. Перечисления Enumerations • Полноценный тип (наравне с классами) • Обладает свойствами класса 
 конструкторы, вычисляемые свойства, динамические методы (у объектов) • Поддерживает расширения (extensions - категории) и протоколы (protocols)
  5. enum Animal { // значения case Dog case Cat case Fish case Robot } enum LazyAnimal { // Одного 'case' достаточно case Dog, Cat, Fish, Robot } По умолчанию значениям не присваиваются 
 Int эквиваленты Каждое значение имеет тип своего перечисления
  6. let pet = Animal.Dog switch pet { case .Dog: println("WOF-WOF") case .Cat: println("MEOW") case .Fish: println("???") case .Robot: println("Death to humans!") }
  7. “Ассоциированные” значения • Каждый объект перечисления может содержать объект другого типа в качестве соответствия • В таком случае их типы могут быть разными • Позволяет “ассоциировать” любую информацию
  8. enum Barcode { case UPCA(Int, Int, Int) case PDF417(String) } var productBarcode = Barcode.UPCA(1, 2, 3) productBarcode = .PDF417("ABCD")
  9. Ассоциированные значения доступны
 в switch-case конструкции
  10. Ассоциированные значения доступны
 в switch-case конструкции switch productBarcode {
  11. Ассоциированные значения доступны
 в switch-case конструкции switch productBarcode { case .UPCA(let system, let ident, let check):
  12. Ассоциированные значения доступны
 в switch-case конструкции switch productBarcode { case .UPCA(let system, let ident, let check): println("UPCA with value of (system), (ident), (check).")
  13. Ассоциированные значения доступны
 в switch-case конструкции switch productBarcode { case .UPCA(let system, let ident, let check): println("UPCA with value of (system), (ident), (check).") case .PDF417(let code):
  14. Ассоциированные значения доступны
 в 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).")
  15. Ассоциированные значения доступны
 в 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).") }
  16. Ассоциированные значения доступны
 в 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).") }
  17. Ассоциированные значения доступны
 в 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
  18. Ассоциированные значения доступны
 в 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 switch productBarcode {
  19. Ассоциированные значения доступны
 в 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 switch productBarcode { case let .UPCA(system, ident, check):
  20. Ассоциированные значения доступны
 в 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 switch productBarcode { case let .UPCA(system, ident, check): println("UPCA with value of (system), (ident), (check).")
  21. Ассоциированные значения доступны
 в 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 switch productBarcode { case let .UPCA(system, ident, check): println("UPCA with value of (system), (ident), (check).") case let .PDF417(code):
  22. Ассоциированные значения доступны
 в 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 switch 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).")
  23. Ассоциированные значения доступны
 в 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 switch 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).") }
  24. “Замещающие” значения • Каждый объект перечисления может быть сопоставлен с объектом другого типа • “Замещающие” значения не меняются (в отличие от “ассоциированных” • Допустимые типы:
 Character, String, Double, Float, Int*
  25. // для 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()
  26. * // свой тип для перечислений 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 } }
  27. • Структура или 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
  28. Generic
  29. Generiс • Одна из самых интересных особенностей Swift • Повышает гибкость и переиспользуемость кода • Swift Standard Library во многом написана с использованием Generic типов
  30. Generic функции
  31. Generic функции func genericSwap<T>(inout a: T, inout b: T) {
  32. Generic функции func genericSwap<T>(inout a: T, inout b: T) { let temp = b
  33. Generic функции func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a
  34. Generic функции func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp
  35. Generic функции func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp }
  36. Generic функции func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp }
  37. Generic функции func genericSwap<T>(inout a: T, inout b: T) { let temp = b b = a a = temp } var a_s = "a"
  38. 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"
  39. 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
  40. 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 var b_i = 2
  41. 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 var b_i = 2 genericSwap(&a_s, &b_s)
  42. 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 var b_i = 2 genericSwap(&a_s, &b_s) genericSwap(&a_i, &b_i)
  43. Generic типы
  44. 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 } }
  45. 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()
  46. Ограничения на типы
  47. Ограничения на типы class MyClass { }
  48. Ограничения на типы class MyClass { } protocol MyProtocol { }
  49. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { }
  50. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { }
  51. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { }
  52. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { }
  53. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { } class Example<T: MyClass, U: MyProtocol> { }
  54. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { } class Example<T: MyClass, U: MyProtocol> { }
  55. Ограничения на типы class MyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { } class Example<T: MyClass, U: MyProtocol> { } // compile error
  56. Ограничения на типы 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>()
  57. Ограничения на типы 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>()
  58. Ограничения на типы 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>()
  59. Ограничения на типы 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
  60. Ассоциированные типы protocol Stack { typealias ObjectType func push(object: ObjectType) func pop() func peek() -> ObjectType? } ObjectType будет объявлен позже: 
 в классе, который реализует протокол
  61. // 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 } }
  62. 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 } }
  63. Протоколы
  64. Александр Зимин iOS developer UX designer azimin@me.com
  65. Протоколы Протокол - это шаблон методов и свойств, которыми будет обладать определенный класс, структура или перечисление, если решит его реализовать
  66. Зачем нужны протоколы
  67. Зачем нужны протоколы 1. Безопасность 
 Протоколы гарантируют проверку на реализацию всех необходимых методов и свойств
  68. Зачем нужны протоколы 1. Безопасность 
 Протоколы гарантируют проверку на реализацию всех необходимых методов и свойств 2. Упрощенное использование 
 Протоколы позволяют разработчику понять, какими свойствами обладает класс, структура или перечисление, не зная конкретный тип
  69. protocol Vehicle { var wheels: Int { get set } var isRequiresFuel: Bool { get } func start() -> String }
  70. 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"
  71. 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
  72. protocol Togglable { mutating func toggle() var state: String { get } }
  73. 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" } } } }
  74. var switcher: Togglable = OnOffSwitch.On switcher.state // "On" switcher.toggle() switcher.state // “Off" func getLamp() -> Togglable var currentLamp: Togglable = getLamp() currentLamp.toggle()
  75. Optionals
  76. Природа Optionals Optional тип - это на самом деле enum, 
 который может содержать либо .None либо .Some(T) Optionals позволяют отследить момент отсутствия значения у переменной
  77. Опциональность в Obj-C У NSObject (супер-класс) могло быть значение nil (NULL). Для Int и прочих базовых типов использовались константы (к примеру NSNotFound), которые определяли какое-то значение (к примеру -1 или INT_MAX)
  78. Обозначения T? - опциональный тип 
 optional type T! - косвенно раскрывающийся опциональный тип 
 implicitly unwrapped optional v? - вызов цепочки от опционального типа 
 optional chaining v! - распаковка опционального типа 
 unwrapping optional
  79. 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
  80. var optionalObject: AnyObject? = nil
 var object: AnyObject = nil 
 COMPILATION ERROR: Type 'AnyObject' does not conform to the protocol 'NilLiteralConvertible
  81. Использование и 
 базовые операции 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 }
  82. Первый “?” позволяет вызвать метод если object != nil Второй “?” вызывает method(params) только если у объекта таковой реализован (respondsToSelector в obj-c) object?.method?(params) var jsonContent: AnyObject? jsonContent?.objectForKey? ("content")?.objectForKey?("info")?[5]
  83. Косвенно раскрывающийся опциональный тип
 implicitly unwrapped optionals var 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)
  84. Вопросы
  85. sergey@pronin.me
Advertisement