Upgrade to Pro — share decks privately, control downloads, hide ads and more …

I love swift.pdf

I love swift.pdf

The Swift overview and the best parts of it

Avatar for Konstantin

Konstantin

August 06, 2014
Tweet

More Decks by Konstantin

Other Decks in Programming

Transcript

  1. Swift Code class Person { var age = 0 var

    name = "" let birthDate: NSDate init(age: Int, name: String) { self.age = age self.name = name birthDate = NSDate.date() } func hello() { println("Hello \(name)") } } ! let me = Person(age: 26, name: "Konstantin") me.hello()
  2. Swift Code class Person { var age = 0 var

    name = "" let birthDate: NSDate init(age: Int, name: String) { self.age = age self.name = name birthDate = NSDate.date() } func hello() { println("Hello \(name)") } } ! let me = Person(age: 26, name: "Konstantin") me.hello() Objective-C @interface Person : NSObject { ! NSInteger age; NSString *name; NSDate *birthDate; } - (instancetype)initWith:(NSInteger)age name:(NSString *)name; - (void)hello; ! @end ! @implementation Person ! - (instancetype)initWith:(NSInteger)anAge name:(NSString *)aName { ! self = [super init]; if (self) { age = anAge; name = aName; birthDate = [NSDate date]; } return self; } ! - (void)hello { NSLog(@"%@",[NSString stringWithFormat:@"Hello %@", name]); } ! @end !
  3. var myAge = 26 var myWifeAge: Int ! var ourAge

    = myAge + myWifeAge ! Static - Strong - Safe
  4. var myAge = 26 var myWifeAge: Int ! myWifeAge =

    18 ! var ourAge = myAge + myWifeAge ! Static - Strong - Safe
  5. var myAge = 26 var myWifeAge: Int ! myWifeAge =

    18 ! var ourAge = myAge + myWifeAge ! ourAge += 1.23 ourAge.count ! Static - Strong - Safe
  6. var myAge = 26 var myWifeAge: Int ! myWifeAge =

    18 ! var ourAge = myAge + myWifeAge ! var numbers = [1,2,3] numbers.count ! numbers.append(4) numbers.append("10") ! Static - Strong - Safe
  7. // Java and C++ Person person = Person(); person.name; A

    bit of History // Objective-C Person* person; person.name; // no Exception when access nil
  8. // Java and C++ Person person = getPerson(); person.name; A

    bit of History // Objective-C Person* person; person.name; // no Exception when access nil // Java and C++ public Person getPerson () { Person(); }
  9. A bit of History // Java and C++ Person person

    = getPerson(); person.name; // Objective-C Person* person; person.name; // no Exception when access nil // Java and C++ public Person getPerson () { ! Person person = fetchFromServer(); person = validate(person) person = checkCreditHistory(person) return person //person is nil }
  10. A bit of History // Java and C++ Person person

    = getPerson(); person.name; // NullPointerException // Objective-C Person* person; person.name; // no Exception when access nil // Java and C++ public Person getPerson () { ! Person person = fetchFromServer(); person = validate(person) person = checkCreditHistory(person) return person //person is nil }
  11. A bit of History // Java and C++ Person person

    = getPerson(); if(person != null) { person.name; } // Objective-C Person* person; person.name; // no Exception when access nil // Java and C++ public Person getPerson () { ! Person person = fetchFromServer(); person = validate(person) person = checkCreditHistory(person) return person //person is nil }
  12. A bit of History // Java and C++ Person person

    = getPerson(); if(person != null) { person.name; } // Objective-C Person* person; if(person) { NSString *name = person.name; if(name) { //Use name } } // Java and C++ public Person getPerson () { ! Person person = fetchFromServer(); person = validate(person) person = checkCreditHistory(person) return person //person is nil }
  13. A bit of History // Java and C++ Person person

    = getPerson(); if(person != null) { person.name; } // Objective-C Person* person; if(person) { NSString *name = person.name; if(name) { //Use name } } // Java and C++ public Person getPerson () { ! Person person = fetchFromServer(); person = validate(person) person = checkCreditHistory(person) return person //person is nil } nil for Scalar value
  14. A bit of History // Java and C++ Person person

    = getPerson(); if(person != null) { person.name; } // Objective-C Person* person; if(person) { NSString *name = person.name; if(name) { //Use name } } // Java and C++ public Person getPerson () { ! Person person = fetchFromServer(); person = validate(person) person = checkCreditHistory(person) return person //person is nil } nil for Scalar value 0 -1 NSNotFound IntMax NULL
  15. Solution ?!? We need language that has a type interface

    for ! • Value • Maybe a Value or Noting
  16. Optionals ! enum Optional<T> { case None case Some(T) }

    func getInt() -> Int { return 10 } func tryGetInt() -> Int? { return nil } ! var a: Int = getInt() var b: Int? = tryGetInt()
  17. Optionals ! enum Optional<T> { case None case Some(T) }

    func getInt() -> Int { return 10 } func tryGetInt() -> Int? { return nil } ! var a: Int = getInt() var b: Int? = tryGetInt() var c: Int? = 20
  18. Optionals ! func getPerson () ->Person { return Person() }

    ! var person = getPerson() person.name ! ! var maybePerson: Person? ! if maybePerson != nil { maybePerson!.name //unwrap optional with ! } ! if let actualPerson = maybePerson { actualPerson.name }
  19. Optionals ! func getPerson () ->Person { return Person() }

    ! var person = getPerson() person.name ! ! var maybePerson: Person? ! if maybePerson != nil { maybePerson!.name //unwrap optional with ! } ! if let actualPerson = maybePerson { actualPerson.name } ! var person: Person? if let person = person { person.name }
  20. Functional • First-class function
 - assign a function to variable


    - pass function as argument to other function 
 - return a function from a function • Closures • Functional programming patterns, : map, filter, etc
  21. Functional func nothing() func printNumber(a : Int) func increase(a: Int)

    -> Int func call(aFunc: (Int) -> (Int) ) -> (Int, Int) ->(Int) () -> () (Int) -> () (Int) -> (Int) ((Int) -> (Int)) -> ((Int, Int) -> (Int))
  22. Functional var c = { (s1: String, s2: String) ->

    Bool in return s1 > s2 } c = { s1, s2 in return s1 > s2 } c = { s1, s2 in s1 > s2 } c = { $0 > $1 } ! (String, String) -> (Bool)
  23. Functional var ar = [1,2,3] // Increase every value in

    array func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result }
  24. Functional var ar = [1,2,3] ar = increase(ar, by:10) //

    [11, 12, 13] func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result }
  25. Functional var ar = [1,2,3] ar = increase(ar, by:10) //

    Decrease every value in array func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result }
  26. Functional var ar = [1,2,3] ar = increase(ar, by:10) //

    Decrease every value in array func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result } ! func decrease(ar :[Int], #by: Int) -> [Int] { var result = ar for var i = 0; i < ar.count; i++ { result[i] -= by } return result }
  27. Functional var ar = [1,2,3] ar = increase(ar, by:10) ar

    = decrease(ar, by:5) // [6, 7, 8] func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result } ! func decrease(ar :[Int], #by: Int) -> [Int] { var result = ar for var i = 0; i < ar.count; i++ { result[i] -= by } return result }
  28. func decrease(ar :[Int], #by: Int) -> [Int] { var result

    = ar for var i = 0; i < ar.count; i++ { result[i] -= by } return result } Functional func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result }
  29. func decrease(ar :[Int], #by: Int) -> [Int] { var result

    = ar for var i = 0; i < ar.count; i++ { result[i] -= by } return result } Functional func increase(ar :[Int], #by: Int) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { result[i] += by } return result } it’s start to smell like a Shit
  30. Functional var ar = [1,2,3] func modify(ar: [Int]) -> [Int]

    { ! var result = ar for var i = 0; i < ar.count; i++ { // Do operation } return result }
  31. Functional var ar = [1,2,3] func modify(ar: [Int], operation: (Int)

    ->(Int) ) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { // Do operation result[i] = operation(ar[i]) } return result }
  32. Functional var ar = [1,2,3] ar = modify(ar, operation: plusOne)

    func modify(ar: [Int], operation: (Int) ->(Int) ) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { // Do operation result[i] = operation(ar[i]) } return result } ! ! func plusOne(a: Int ) -> Int { return a + 1 }
  33. Functional var ar = [1,2,3] ar = modify(ar) { $0

    + 1 } ar = modify(ar) { $0 - 2 } ar = modify(ar) { $0 * 2 } func modify(ar: [Int], operation: (Int) ->(Int) ) -> [Int] { ! var result = ar for var i = 0; i < ar.count; i++ { // Do operation result[i] = operation(ar[i]) } return result }
  34. Functional var ar = [1,2,3] ! ar.map { $0 -

    2 } ar.filter { $0 % 2 == 0 } ar.reduce(0, combine: +)
  35. OOP

  36. OOP •Classes •Protocols •Properties • Methods • Initialisers • Deinitializers

    • Property observers • Inheritance • Access control • Lazy loading • Subscript All the feature of modern OOP Language
  37. OOP class Person { var age = 0 var name

    = "Default" var secondName = "Default" lazy var importer = DataImporter() ! init(age: Int, name: String) { self.age = age self.name = name } ! deinit { println("say goodbye") } func hello() { println("Hello \(name)") } var fullName: String { return name + " " + secondName } }
  38. OOP class Parent : Person { ! var children :[Person]

    override init(age: Int, name: String) { children = [] super.init(age: age, name: name) } override var age: Int { willSet { println("age will be changed") } didSet { println("age is changed") } } subscript(index: Int) -> Person { get { return children[index] } set(newValue) { children[index] = newValue } } }
  39. Objects Initialisations • Must set value for all the properties

    • After memory is fully initialised can access self • Subclasses initialisers must delegate up (call super.init) • Designated and Connivance initialisers • Not inherited by default
  40. Objects Initialisations class Parent : Person { var childName !

    init(children: [Person], age: Int, name: String) { self.children = children super.init(age: age, name: name) } }
  41. Objects Initialisations class Parent : Person { var childName !

    init(children: [Person], age: Int, name: String) { self.children = children super.init(age: age, name: name) } ! override init(age: Int, name: String) { children = [] super.init(age: age, name: name) } }
  42. Objects Initialisations class Parent : Person { var childName !

    init(children: [Person], age: Int, name: String) { self.children = children super.init(age: age, name: name) } ! override init(age: Int, name: String) { children = [] super.init(age: age, name: name) } ! ! convenience init () { self.init(age:0, name:"") } }
  43. Generics • Flexible, reusable functions and types that can work

    with any type ! • Less boilerplate code
  44. Generics var a = 10 var b = 20 !

    swapInt(&a, &b) func swapInt(inout a: Int, inout b: Int) { let tmp = a a = b b = tmp }
  45. Generics var a = 10 var b = 20 !

    swapInt(&a, &b) ! var str1 = "One" var str2 = “Two" func swapInt(inout a: Int, inout b: Int) { let tmp = a a = b b = tmp } !
  46. Generics var a = 10 var b = 20 !

    swapInt(&a, &b) ! var str1 = "One" var str2 = “Two" func swapInt(inout a: Int, inout b: Int) { let tmp = a a = b b = tmp } ! func swapSting(inout a: String, inout b: String) { let tmp = a a = b b = tmp }
  47. Generics var a = 10 var b = 20 !

    swapInt(&a, &b) ! var str1 = "One" var str2 = “Two” ! swapSting(&str1, &str2) func swapInt(inout a: Int, inout b: Int) { let tmp = a a = b b = tmp } ! func swapSting(inout a: String, inout b: String) { let tmp = a a = b b = tmp }
  48. Generics var a = 10 var b = 20 !

    swapInt(&a, &b) ! var str1 = "One" var str2 = “Two” ! swapSting(&str1, &str2) func swapInt(inout a: Int, inout b: Int) { let tmp = a a = b b = tmp } ! func swapSting(inout a: String, inout b: String) { let tmp = a a = b b = tmp }
  49. Generics var a = 10 var b = 20 !

    swapInt(&a, &b) ! var str1 = "One" var str2 = “Two” ! swapSting(&str1, &str2) func swapInt(inout a: Int, inout b: Int) { let tmp = a a = b b = tmp } ! func swapSting(inout a: String, inout b: String) { let tmp = a a = b b = tmp } Do you feel this smell ??
  50. Generics var a = 10 var b = 20 var

    str1 = "One" var str2 = “Two” ! swap(&a, &b) swap(&str1, &str2) func swap<T>(inout a: T, inout b: T) { let tmp = a a = b b = tmp }
  51. Generics var a = 10 var b = 20 var

    str1 = "One" var str2 = “Two” ! swap(&a, &b) swap(&str1, &str2) ! min(1, 10) min("a", "J") func swap<T>(inout a: T, inout b: T) { let tmp = a a = b b = tmp } ! func min<T : Comparable>(x: T, y: T) -> T { return x < y ? x : y }
  52. Generics var a = 10 var b = 20 var

    str1 = "One" var str2 = “Two” ! swap(&a, &b) swap(&str1, &str2) ! min(1, 10) min("a", “J") minElement(10, 3, 1, 4) func min<T : Comparable>(x: T, y: T) -> T { return x < y ? x : y } ! func minElement<R : SequenceType where R.Element : Comparable>(range: R) -> R.Generator.Element { ! var min: R.Element? for object in range { if min == nil || object < min { min = object } } return min! }
  53. Immutable var name = "Konstantin" name = "Tomas" name +=

    " Super” ! let superName = "Super Konstantin”
  54. Immutable var name = "Konstantin" name = "Tomas" name +=

    " Super” ! let superName = "Super Konstantin” ! superName = "Tomas" superName += "and Tomas" !
  55. Immutable var name = "Konstantin" name = “Tomas" name +=

    " Super” ! let superName = "Super Konstantin” ! var people = ["Jon", "Sam"] people.append("Arnold") // ["Jon", "Sam", "Arnold"] ! let superPeople = ["Konstantin", "Rikke"] !
  56. Immutable var name = "Konstantin" name = “Tomas" name +=

    " Super” ! let superName = "Super Konstantin” ! var people = ["Jon", "Sam"] people.append("Arnold") // ["Jon", "Sam", "Arnold"] ! let superPeople = ["Konstantin", "Rikke"] superPeople.append("Tomas") !
  57. Immutable struct Rocketfarm { ! var people: [String] mutating func

    append (person: String) { people.append(person) } } ! var rocket = Rocketfarm(people: ["Halvor", "Jørn", "Dyre"]) rocket.append("Konstantin") !
  58. Immutable struct Rocketfarm { ! var people: [String] mutating func

    append (person: String) { people.append(person) } } ! var rocket = Rocketfarm(people: ["Halvor", "Jørn", "Dyre"]) rocket.append("Konstantin") ! let secondRocket = rocket secondRocket.append("Lars") !
  59. Tuples • Group multiple values into a single compound value

    • Can be of any type • Do not have to be of the same type • Tuples are particularly useful as the return values of functions.
  60. Tuples let http404Error = (404, "Not Found”) http404Error.0 http404Error.1 !

    let http200Error = (statusCode:404, description:"Not Found") http200Error.statusCode http200Error.description !
  61. Tuples func getServerContent() ->(data: String?, error:(errorCode: Int, description: String)? )

    { return ("data from server", nil) } ! let res = getServerContent() ! res.error res.data ! if let error = res.error { println("Error \(error.description) with code: \(error.errorCode)") }
  62. Custom Operators • Overload existing operator for new types •

    Create new operator Why ? - Make code more verbose and readable
  63. Custom Operators public class Rocketfarm { var people: [String] =

    [] ! func append (person: String) { people.append(person) } } var rocket = Rocketfarm() rocket.append("Konstantin")
  64. Custom Operators public class Rocketfarm { var people: [String] =

    [] ! func append (person: String) { people.append(person) } } var rocket = Rocketfarm() rocket.append("Konstantin") ! rocket + "Stian" rocket << "Dyre"
  65. Custom Operators public class Rocketfarm { var people: [String] =

    [] ! func append (person: String) { people.append(person) } } ! public func + (rocket: Rocketfarm, person: String) -> Rocketfarm { var newRocket = rocket newRocket.append(person) return newRocket } ! public func << (rocket: Rocketfarm, person: String) -> Rocketfarm { return rocket + person } var rocket = Rocketfarm() rocket.append("Konstantin") ! rocket + "Stian" rocket << "Dyre"
  66. Custom Operators var rocket = Rocketfarm() rocket.append("Konstantin") ! rocket +

    "Stian" rocket << “Dyre" ! rocket^^^ ! postfix operator ^^^ {}
  67. Custom Operators var rocket = Rocketfarm() rocket.append("Konstantin") ! rocket +

    "Stian" rocket << “Dyre" ! rocket^^^ ! postfix operator ^^^ {} postfix func ^^^ (rocket: Rocketfarm) -> Rocketfarm { var newRocket = rocket newRocket.people.removeAll() return newRocket }
  68. Pattern Matching It’s very smart switch statement • Must be

    exhaustive, (handle all cases) • Implicit Fall through • Range Matching • Value Bindings • Where condition
  69. Pattern Matching let size = (20, 40) ! switch size

    { ! case (0, 0): println("(0, 0) rect”) ! default: println("some rectangle") }
  70. Pattern Matching let size = (20, 40) ! switch size

    { ! case (0, 0): println("(0, 0) rect”) ! case let (width, height) where width == height: println("square with sides \(width)”) ! case (1...10, 1...10): println("small rectangle”) ! case let (width, height): println("rectangle with width \(width) and height \(height)") }
  71. Pattern Matching let integerToDescribe = 5 var description = "The

    number \(integerToDescribe) is" ! switch integerToDescribe { ! case 2, 3, 5, 7, 11, 13, 17, 19: description += " a prime number, and also" fallthrough ! default: description += " an integer." }
  72. Seamless migration Swift Objective-C • 100 % Objective-C code available

    in swift • Automatically generated interface headers • All standard frameworks • All custom libraries (All the goodies from Github) • 80 % Swift code available in swift Swift features (Tuples, Optionals) is not available • Mark Swift class as Objective-C compatible @objc
  73. Seamless migration Swift var view = UIView() view.backgroundColor = UIColor.greenColor()

    var label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) label.text = "Happinessssss!"
  74. Seamless migration Swift Objective-C @objc class A { ! var

    name = "Name" lazy var subName = " " var count: Int? var tuple = (10, "Ten") class func newInstance () -> A { return A() } ! func hello() { println("Hello") } } #import “ProjectName-Swift.h" ! A* a = [A newInstance]; [a hello]; a.name; a.subName; ! // Not available a.count; a.tuple;
  75. Seamless migration “ProjectName-Swift.h" File content "ProjectName-Swift.h" ! SWIFT_CLASS("_TtC9ProjectNameA") @interface A

    @property (nonatomic, copy) NSString * name; @property (nonatomic, copy) NSString * subName; - (instancetype)init OBJC_DESIGNATED_INITIALIZER; + (A *)newInstance; - (void)hello; @end
  76. Much More • Ranges • Enums with values • Nested

    Functions • Default parameters • Variadic parameters • External and Internal names • Extensions • Type casting • Nested Types • Optional Chaining • ARC (Automatic Reference Counting) • @autoclosure • Namespaces
  77. Final Word 2 - Java 3 - Objective-C 16 -

    Swift 40 - Scala Tiobe Index Fast - Faster than C Popular And trending 1,0 x 2,8 x 3,9 x Swift Objective-C Python