Swift Школа
Сергей Пронин
Empatika
План
• Перечисления
• Generic
• Протоколы
• Optionals
Перечисления
Перечисления
Enumerations
• Полноценный тип (наравне с классами)
• Обладает свойствами класса 

конструкторы, вычисляемые свойства,
динамические методы (у объектов)
• Поддерживает расширения (extensions -
категории) и протоколы (protocols)
enum Animal {
// значения
case Dog
case Cat
case Fish
case Robot
}
enum LazyAnimal {
// Одного 'case' достаточно
case Dog, Cat, Fish, Robot
}
По умолчанию значениям не присваиваются 

Int эквиваленты
Каждое значение имеет тип своего перечисления
let pet = Animal.Dog
switch pet {
case .Dog:
println("WOF-WOF")
case .Cat:
println("MEOW")
case .Fish:
println("???")
case .Robot:
println("Death to humans!")
}
“Ассоциированные” значения
• Каждый объект перечисления может
содержать объект другого типа в качестве
соответствия
• В таком случае их типы могут быть разными
• Позволяет “ассоциировать” любую
информацию
enum Barcode {
case UPCA(Int, Int, Int)
case PDF417(String)
}
var productBarcode = Barcode.UPCA(1, 2, 3)
productBarcode = .PDF417("ABCD")
Ассоциированные значения доступны

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

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

в switch-case конструкции
switch productBarcode {
case .UPCA(let system, let ident, let check):
Ассоциированные значения доступны

в switch-case конструкции
switch productBarcode {
case .UPCA(let system, let ident, let check):
println("UPCA with value of (system), (ident), (check).")
Ассоциированные значения доступны

в switch-case конструкции
switch productBarcode {
case .UPCA(let system, let ident, let check):
println("UPCA with value of (system), (ident), (check).")
case .PDF417(let code):
Ассоциированные значения доступны

в 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).")
Ассоциированные значения доступны

в 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).")
}
Ассоциированные значения доступны

в 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).")
}
Ассоциированные значения доступны

в 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-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 {
Ассоциированные значения доступны

в 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):
Ассоциированные значения доступны

в 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).")
Ассоциированные значения доступны

в 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):
Ассоциированные значения доступны

в 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).")
Ассоциированные значения доступны

в 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).")
}
“Замещающие” значения
• Каждый объект перечисления может быть
сопоставлен с объектом другого типа
• “Замещающие” значения не меняются (в
отличие от “ассоциированных”
• Допустимые типы:

Character, String, Double, Float, Int*
// для 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()
*
// свой тип для перечислений
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
}
}
• Структура или 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
Generic
Generiс
• Одна из самых интересных особенностей Swift
• Повышает гибкость и переиспользуемость кода
• Swift Standard Library во многом написана с
использованием Generic типов
Generic функции
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
let temp = b
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
let temp = b
b = a
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
let temp = b
b = a
a = temp
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
let temp = b
b = a
a = temp
}
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
let temp = b
b = a
a = temp
}
Generic функции
func genericSwap<T>(inout a: T, inout b: T) {
let temp = b
b = a
a = temp
}
var a_s = "a"
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"
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
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
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)
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)
Generic типы
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
}
}
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()
Ограничения на типы
Ограничения на типы
class MyClass { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
class MyClass2: MyClass { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
class MyClass2: MyClass { }
class MyClass3: MyClass, MyProtocol { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
class MyClass2: MyClass { }
class MyClass3: MyClass, MyProtocol { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
class MyClass2: MyClass { }
class MyClass3: MyClass, MyProtocol { }
class Example<T: MyClass, U: MyProtocol> { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
class MyClass2: MyClass { }
class MyClass3: MyClass, MyProtocol { }
class Example<T: MyClass, U: MyProtocol> { }
Ограничения на типы
class MyClass { }
protocol MyProtocol { }
class MyClassWithProtocol: MyProtocol { }
class MyClass2: MyClass { }
class MyClass3: MyClass, MyProtocol { }
class Example<T: MyClass, U: MyProtocol> { }
// compile error
Ограничения на типы
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>()
Ограничения на типы
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>()
Ограничения на типы
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>()
Ограничения на типы
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
Ассоциированные типы
protocol Stack {
typealias ObjectType
func push(object: ObjectType)
func pop()
func peek() -> ObjectType?
}
ObjectType будет объявлен позже: 

в классе, который реализует протокол
// 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
}
}
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
}
}
Протоколы
Александр Зимин
iOS developer
UX designer
azimin@me.com
Протоколы
Протокол - это шаблон методов и свойств,
которыми будет обладать определенный класс,
структура или перечисление, если решит его
реализовать
Зачем нужны протоколы
Зачем нужны протоколы
1. Безопасность 

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

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

Протоколы позволяют разработчику понять, какими
свойствами обладает класс, структура или
перечисление, не зная конкретный тип
protocol Vehicle {
var wheels: Int { get set }
var isRequiresFuel: Bool { get }
func start() -> String
}
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"
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
protocol Togglable {
mutating func toggle()
var state: String { get }
}
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"
}
}
}
}
var switcher: Togglable = OnOffSwitch.On
switcher.state // "On"
switcher.toggle()
switcher.state // “Off"
func getLamp() -> Togglable
var currentLamp: Togglable = getLamp()
currentLamp.toggle()
Optionals
Природа Optionals
Optional тип - это на самом деле enum, 

который может содержать либо .None либо .Some(T)
Optionals позволяют отследить момент отсутствия
значения у переменной
Опциональность в Obj-C
У NSObject (супер-класс) могло быть значение nil
(NULL).
Для Int и прочих базовых типов использовались
константы (к примеру NSNotFound), которые
определяли какое-то значение (к примеру -1 или
INT_MAX)
Обозначения
T? - опциональный тип 

optional type

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

implicitly unwrapped optional

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

optional chaining

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

unwrapping optional
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
var optionalObject: AnyObject? = nil

var object: AnyObject = nil 

COMPILATION ERROR: Type 'AnyObject' does
not conform to the protocol
'NilLiteralConvertible
Использование и 

базовые операции
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
}
Первый “?” позволяет вызвать метод если object != nil
Второй “?” вызывает method(params) только если у объекта
таковой реализован (respondsToSelector в obj-c)
object?.method?(params)
var jsonContent: AnyObject?
jsonContent?.objectForKey?
("content")?.objectForKey?("info")?[5]
Косвенно раскрывающийся
опциональный тип

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)
Вопросы
sergey@pronin.me

Swift School #2

  • 1.
  • 2.
  • 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 { caseUPCA(Int, Int, Int) case PDF417(String) } var productBarcode = Barcode.UPCA(1, 2, 3) productBarcode = .PDF417("ABCD")
  • 9.
  • 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.
  • 29.
    Generiс • Одна изсамых интересных особенностей Swift • Повышает гибкость и переиспользуемость кода • Swift Standard Library во многом написана с использованием Generic типов
  • 30.
  • 31.
  • 32.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b
  • 33.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b b = a
  • 34.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b b = a a = temp
  • 35.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b b = a a = temp }
  • 36.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b b = a a = temp }
  • 37.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b b = a a = temp } var a_s = "a"
  • 38.
    Generic функции func genericSwap<T>(inouta: T, inout b: T) { let temp = b b = a a = temp } var a_s = "a" var b_s = "a"
  • 39.
    Generic функции func genericSwap<T>(inouta: 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>(inouta: 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>(inouta: 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>(inouta: 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.
  • 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.
  • 48.
    Ограничения на типы classMyClass { } protocol MyProtocol { }
  • 49.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { }
  • 50.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { }
  • 51.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { }
  • 52.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { }
  • 53.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { } class Example<T: MyClass, U: MyProtocol> { }
  • 54.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { } class Example<T: MyClass, U: MyProtocol> { }
  • 55.
    Ограничения на типы classMyClass { } protocol MyProtocol { } class MyClassWithProtocol: MyProtocol { } class MyClass2: MyClass { } class MyClass3: MyClass, MyProtocol { } class Example<T: MyClass, U: MyProtocol> { } // compile error
  • 56.
    Ограничения на типы classMyClass { } 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.
    Ограничения на типы classMyClass { } 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.
    Ограничения на типы classMyClass { } 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.
    Ограничения на типы classMyClass { } 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.
  • 65.
    Протоколы Протокол - этошаблон методов и свойств, которыми будет обладать определенный класс, структура или перечисление, если решит его реализовать
  • 66.
  • 67.
    Зачем нужны протоколы 1.Безопасность 
 Протоколы гарантируют проверку на реализацию всех необходимых методов и свойств
  • 68.
    Зачем нужны протоколы 1.Безопасность 
 Протоколы гарантируют проверку на реализацию всех необходимых методов и свойств 2. Упрощенное использование 
 Протоколы позволяют разработчику понять, какими свойствами обладает класс, структура или перечисление, не зная конкретный тип
  • 69.
    protocol Vehicle { varwheels: 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 { mutatingfunc 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.
  • 76.
    Природа Optionals Optional тип- это на самом деле enum, 
 который может содержать либо .None либо .Some(T) Optionals позволяют отследить момент отсутствия значения у переменной
  • 77.
    Опциональность в Obj-C УNSObject (супер-класс) могло быть значение nil (NULL). Для Int и прочих базовых типов использовались константы (к примеру NSNotFound), которые определяли какое-то значение (к примеру -1 или INT_MAX)
  • 79.
    Обозначения T? - опциональныйтип 
 optional type T! - косвенно раскрывающийся опциональный тип 
 implicitly unwrapped optional v? - вызов цепочки от опционального типа 
 optional chaining v! - распаковка опционального типа 
 unwrapping optional
  • 80.
    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
  • 81.
    var optionalObject: AnyObject?= nil
 var object: AnyObject = nil 
 COMPILATION ERROR: Type 'AnyObject' does not conform to the protocol 'NilLiteralConvertible
  • 82.
    Использование и 
 базовыеоперации 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 }
  • 83.
    Первый “?” позволяетвызвать метод если object != nil Второй “?” вызывает method(params) только если у объекта таковой реализован (respondsToSelector в obj-c) object?.method?(params) var jsonContent: AnyObject? jsonContent?.objectForKey? ("content")?.objectForKey?("info")?[5]
  • 84.
    Косвенно раскрывающийся опциональный тип
 implicitlyunwrapped 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)
  • 85.
  • 86.