A Swift Introduction

A Swift Introduction

Apple has introduced a brand-new programming language to the world. Now at 1.0, Swift is here to make your iOS and OS X apps more awesome. Let’s take a look at the language, how it’s used, and play with it! This session assumes no previous experience with Apple platforms or Objective-C, though we will compare Swift code to Objective-C code to see just how much better it can make some programming tasks. Much of this session will take place inside of an iOS Playground in Swift. We will see code live in Apple’s new REPL which was inspired by Light Table.

8d92e9730c561c120200f34e7e50ed46?s=128

Jeff Kelley

November 15, 2014
Tweet

Transcript

  1. A Swift Introduction Jeff Kelley, 1DevDay Detroit November 15th, 2014

  2. None
  3. None
  4. None
  5. None
  6. None
  7. None
  8. None
  9. None
  10. None
  11. None
  12. None
  13. None
  14. None
  15. None
  16. None
  17. [Swift] greatly benefited from the experiences hard-won by many other

    languages in the field, drawing ideas from Objective-C, Rust, Haskell, Ruby, Python, C#, CLU, and far too many others to list. Playgrounds were heavily influenced by Bret Victor's ideas, by Light Table and by many other interactive systems.
  18. None
  19. None
  20. None
  21. Variables var answerToEverything = 42
 var answerToEverything: Int = 42


    let constantAnswer = 42
 let constantAnswer: Double = 42
  22. Variables var answerToEverything: Int = 42
 let constantAnswer: Int =

    42
 answerToEverything += 1 constantAnswer = 43;
  23. Variables var answerToEverything: Int = 42 let constantAnswer: Int =

    42 answerToEverything += 1 constantAnswer = 43;
  24. Variables var = "poo" let = "dog" var = "poo"

    let = "dog"
  25. Functions func reverseString(string: String) -> String { var output =

    "" for character in string { output = character + output } return output }
  26. Functions let myName = "Jeff" func reverseString(string: String) -> String

    { var output = "" for character in string { output = character + output } return output } reverseString(myName) // Outputs "ffeJ"
  27. Functions func printEmojiForAnimals(: Character, : Character, : Character, : Character)

    { println("Dog: \()") println("Cat: \()") println("Horse: \()") println("Cow: \()") } printEmojiForAnimals("", "", "", "")
  28. Functions func printEmojiForAnimals(dog : Character, cat : Character, horse :

    Character, cow : Character) { println("Dog: \()") println("Cat: \()") println("Horse: \()") println("Cow: \()") } printEmojiForAnimals(dog: "", cat: "", horse: "", cow: "")
  29. Functions func printEmojiForAnimals(dog : Character = "", cat : Character

    = "", horse : Character = "", cow : Character = "") { println("Dog: \()") println("Cat: \()") println("Horse: \()") println("Cow: \()") } printEmojiForAnimals(dog: "", cat: "", horse: "", cow: "")
  30. Functions func printEmojiForAnimals(dog : Character = "", cat : Character

    = "", horse : Character = "", cow : Character = "") { println("Dog: \()") println("Cat: \()") println("Horse: \()") println("Cow: \()") } printEmojiForAnimals()
  31. Functions func printEmojiForAnimals(dog : Character = "", cat : Character

    = "", horse : Character = "", cow : Character = "") { println("Dog: \()") println("Cat: \()") println("Horse: \()") println("Cow: \()") } printEmojiForAnimals(cat: "")
  32. Multiple Return Values func bounds(integers: [Int]) -> (min: Int, max:

    Int) { var min = Int.max var max = Int.min for n in integers { if (n < min) { min = n } if (n > max) { max = n } } return (min, max) } var result = bounds([1,2,3,4]) var min = result.min // 1 var max = result.max // 4
  33. Arrays var someObjects = ["foo", "bar", "baz", 42] var someStrings

    = ["foo", "bar", "baz"] someStrings.append(42)
  34. Arrays var someObjects: [AnyObject] = ["foo", "bar", "baz", 42] var

    someStrings: [String] = ["foo", "bar", "baz"] someStrings.append(42)
  35. Arrays var someObjects: [AnyObject] = ["foo", "bar", "baz", 42] var

    someStrings: [String] = ["foo", "bar", "baz"] someStrings.append(42)
  36. Array Mutability let theOnlyStrings = ["foo", "bar"] theOnlyStrings.append("baz")

  37. Array Mutability let theOnlyStrings = ["foo", "bar"] theOnlyStrings.append("baz")

  38. Dictionaries var favoriteIDEs = ["Amber": "AppCode", "Jeff": "Xcode"] favoriteIDEs["Nate"] =

    "whatever tool is best for Scala" println("Nate’s favorite IDE is " + favoriteIDEs["Nate"]!) // Outputs “Nate’s favorite IDE is whatever tool is best for Scala”
  39. Dictionaries var favoriteIDEs println // Outputs “Nate’s favorite IDE is

    whatever tool is best for Scala” var favoriteIDEs = ["Amber": "AppCode", "Jeff": "Xcode"] favoriteIDEs["Nate"] = "whatever tool is best for Scala" println("Nate’s favorite IDE is " + favoriteIDEs["Nate"]!) // Outputs “Nate’s favorite IDE is whatever tool is best for Scala”
  40. Optionals var hasPermission: Bool? if (hasPermission != nil) { if

    (hasPermission!) { // Do something with permission } else { // You don’t have permission! } } else { // Ask for permission }
  41. Optionals var hasPermission: Bool? if let givenPermission = hasPermission {

    if (givenPermission) { // Do something with permission } else { // You don’t have permission! } } else { // Ask for permission }
  42. Optionals func logWithOptionalString(string: String? = nil) { if let message

    = string { NSLog("Received message %@", message) } else { NSLog("Logged with no message") } } logWithOptionalString(string: "Hello") logWithOptionalString()
  43. Classes class Animal { var color: NSColor var name: String

    init (color: NSColor, name: String) { self.color = color self.name = name } } class Dog : Animal { var chasesCars: Bool init(color: NSColor, name: String, chasesCars: Bool) { self.chasesCars = chasesCars super.init(color: color, name: name) } func bark() -> () { println("Woof!") } } var Bella = Dog(color: NSColor.whiteColor(), name: "Bella", chasesCars: false)
  44. Classes class Animal { var color: NSColor let name: String

    init (color: NSColor, name: String) { self.color = color self.name = name } } class Dog : Animal { var chasesCars: Bool init(color: NSColor, name: String, chasesCars: Bool) { self.chasesCars = chasesCars super.init(color: color, name: name) } func bark() -> () { println("Woof!") } } var Bella = Dog(color: NSColor.whiteColor(), name: "Bella", chasesCars: false)
  45. Classes class Dog : Animal { var chasesCars: Bool =

    true init(color: NSColor, name: String, chasesCars: Bool) { self.chasesCars = chasesCars super.init(color: color, name: name) } func bark() { println("Woof!") } } class Chihuahua : Dog { override func bark() { println("Yip yip yip yip!") } }
  46. Classes typealias Doge = Dog class Shibe : Doge {

    init(name: String) { super.init(color: NSColor.orangeColor(), name: name, chasesCars: false) } override func bark() { println("wow") } } var superShibe = Shibe(name: "much subclass")
  47. Classes class Cat : Animal { let cares = false

    }
  48. Classes class : Animal { let cares = false }

    var kitty = (color: NSColor.whiteColor(), name: "Kitty Cat");
  49. Constant Objects let kitty = (color: NSColor.whiteColor(), name: "Kitty Cat");

    kitty.color = NSColor.blueColor()
  50. Extensions extension Dog { func goToBed() { walkInACircle() walkInACircle() walkInACircle()

    walkInACircle() lieDown() } }
  51. Extensions extension NSView { func makeKindaTransparent() { self.alphaValue = 0.5

    } }
  52. Extensions extension CGRect { func area() -> CGFloat { return

    CGRectGetWidth(self) * CGRectGetHeight(self) } } var rect = CGRect(x: 100, y: 100, width: 512, height: 512) rect.area() // 262144.0
  53. Structs struct SolarSystem { let star: Star var planets: [Planet]?

    } let ourSystem = SolarSystem(star: sol, planets: [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune])
  54. Structs struct SolarSystem { let star: Star var planets: [Planet]?

    func description() -> String { var description = "The \(star.name) system" if let planets = planets { description += ", orbited by " for i in 0 ..< planets.count { description += planets[i].name if (i + 2 == planets.count) { description += ", and " } else if (i + 1 < planets.count) { description += ", " } } } return description } } let ourSystem = SolarSystem(star: sol, planets: [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune]) ourSystem.description() // The Sol system, orbited by Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune
  55. Structs struct SolarSystem { let star: Star var planets: [Planet]?

    } extension SolarSystem { func description() -> String { var description = "The \(star.name) system" if let planets = planets { description += ", orbited by " for i in 0 ..< planets.count { description += planets[i].name if (i + 2 == planets.count) { description += ", and " } else if (i + 1 < planets.count) { description += ", " } } } return description } } let ourSystem = SolarSystem(star: sol, planets: [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune]) ourSystem.description() // The Sol system, orbited by Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune
  56. Struct Mutability struct SolarSystem { let star: Star var planets:

    [Planet]? } let ourSystem = SolarSystem(star: sol, planets: [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune]) if (ourSystem.planets != nil) { ourSystem.planets!.append(pluto) }
  57. Struct Mutability struct SolarSystem { let star: Star var planets:

    [Planet]? } let ourSystem = SolarSystem(star: sol, planets: [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune]) if (ourSystem.planets != nil) { ourSystem.planets!.append(pluto) }
  58. Struct Mutability struct SolarSystem { let star: Star var planets:

    [Planet]? } var ourSystem = SolarSystem(star: sol, planets: [mercury, venus, earth, mars, jupiter, saturn, uranus, neptune]) if (ourSystem.planets != nil) { ourSystem.planets!.append(pluto) } ourSystem.planets!.count // 9
  59. Classes vs. Structs struct Article { var title: String var

    byline: String var content: String mutating func fixTitleCase() { self.title = self.title.capitalizedString } } class ArticlePreparer { var article: Article init(article: Article) { self.article = article } func prepareForSubmission() { article.fixTitleCase() } } var swiftIsAwesome = Article(title: "Swift is awesome", byline: "by Jeff Kelley", content: " is a valid class name.") var preparer = ArticlePreparer(article: swiftIsAwesome) preparer.prepareForSubmission() swiftIsAwesome.title // "Swift is awesome"
  60. Classes vs. Structs class Article { var title: String var

    byline: String var content: String init(title: String, byline: String, content: String) { self.title = title self.byline = byline self.content = content } func fixTitleCase() { self.title = self.title.capitalizedString } } class ArticlePreparer { var article: Article init(article: Article) { self.article = article } func prepareForSubmission() { article.fixTitleCase() } } var swiftIsAwesome = Article(title: "Swift is awesome", byline: "by Jeff Kelley", content: " is a valid class name.") var preparer = ArticlePreparer(article: swiftIsAwesome) preparer.prepareForSubmission() swiftIsAwesome.title // "Swift Is Awesome"
  61. Classes vs. Structs Classes • Passed by reference • Require

    you to define initializers • Extensible • Can mutate selves inside of functions Structs • Passed by value • Automatic initializers with every variable • Extensible • Must decorate mutating functions
  62. Arrays and Dictionaries are Structs! struct Array<T> : MutableCollectionType, Sliceable

    { typealias Element = T var startIndex: Int { get } var endIndex: Int { get } subscript (index: Int) -> T func generate() -> IndexingGenerator<[T]> typealias SubSlice = Slice<T> subscript (subRange: Range<Int>) -> Slice<T> /// Initialization from an existing buffer does not have "array.init" /// semantics because the caller may retain an alias to buffer. init(_ buffer: _ArrayBuffer<T>) } … struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible { typealias Element = (Key, Value) typealias Index = DictionaryIndex<Key, Value> /// Create a dictionary with at least the given number of /// elements worth of storage. The actual capacity will be the /// smallest power of 2 that's >= `minimumCapacity`. init(minimumCapacity: Int = default) var startIndex: DictionaryIndex<Key, Value> { get } var endIndex: DictionaryIndex<Key, Value> { get } …
  63. Enums enum ArticleType { case Opinion case LongForm case PoliticalCartoon

    case Editorial case LetterToTheEditor case PoemByEECummings } class Article { var title: String var byline: String var content: String let type: ArticleType … } var swiftIsAwesome = Article(title: "Swift is awesome", byline: "by Jeff Kelley", content: " is a valid class name.", type:.Opinion)
  64. Enums class Article { var title: String var byline: String

    var content: String let type: ArticleType func fixTitleCase() { switch type { case .PoemByEECummings: self.title = self.title.lowercaseString default: self.title = self.title.capitalizedString } } }
  65. Enums enum ArticleType { case Opinion case LongForm case PoliticalCartoon([NSImage])

    case Editorial case LetterToTheEditor case PoemByEECummings } extension Article { func fixTitle() { switch type { case .PoliticalCartoon(let images): self.title = self.title.capitalizedString + " (\(images.count) panels)" case .PoemByEECummings: self.title = self.title.lowercaseString default: self.title = self.title.capitalizedString } } }
  66. Optionals enum Optional<T> { case None case Some(T) }

  67. Generics func mySwap<T>(inout a: T, inout b: T) { var

    c = b b = a a = c } var a = 42 var b = 9_001 mySwap(&a, &b) a // 9001 b // 42
  68. Closures func sortByGravity(p1: Planet, p2: Planet) -> Bool { return

    p1.gravity > p2.gravity } var sortedPlanets = ourSystem.planets!.sorted(sortByGravity)
  69. Closures var sortedPlanets: [Planet] = ourSystem.planets!.sorted({ (p1: Planet, p2: Planet)

    -> Bool in return p1.gravity > p2.gravity })
  70. Closures var sortedPlanets: [Planet] = ourSystem.planets!.sorted { (p1: Planet, p2:

    Planet) -> Bool in return p1.gravity > p2.gravity }
  71. Closures var sortedPlanets = ourSystem.planets!.sorted { (p1: Planet, p2: Planet)

    -> Bool in return p1.gravity > p2.gravity }
  72. Closures var sortedPlanets = ourSystem.planets!.sorted { (p1, p2) -> Bool

    in return p1.gravity > p2.gravity }
  73. Closures var sortedPlanets = ourSystem.planets!.sorted { p1, p2 in return

    p1.gravity > p2.gravity }
  74. Closures var sortedPlanets = ourSystem.planets!.sorted { p1, p2 in p1.gravity

    > p2.gravity }
  75. Closures var sortedPlanets = ourSystem.planets!.sorted { $0.gravity > $1.gravity }

  76. Closures var sortedPlanets = ourSystem.planets!.sorted { $0.gravity > $1.gravity }

  77. Closures func > (left: Planet, right: Planet) -> Bool {

    return left.gravity > right.gravity } var sortedPlanets = ourSystem.planets!.sorted { $0 > $1 }
  78. Closures func > (left: Planet, right: Planet) -> Bool {

    return left.gravity > right.gravity } var sortedPlanets = ourSystem.planets!.sorted(>)
  79. Closures var sortedPlanets: [Planet]= ourSystem.planets!.sorted({ (p1: Planet, p2: Planet) ->

    Bool in return p1.gravity > p2.gravity }) var sortedPlanets = ourSystem.planets!.sorted(>)
  80. None
  81. Objective-C Interoperability • Swift Classes can inherit from Objective-C Classes

    • Objective-C Classes can inherit from Swift Classes • Swift can extend C structs with functions • Swift code can call Objective-C methods • Objective-C code can call Swift functions • Swift code can call C functions (even malloc())
  82. Thanks! • @SlaunchaMan on Twitter • SlaunchaMan@gmail.com • “Swift InFlux”:

    github.com/ksm/SwiftInFlux