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

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