Swift 语言最小化

PauKohn 5年前
   <p style="text-align:center"><img src="https://simg.open-open.com/show/a3b31a7d4655347ef58ecdb5c94aa953.jpg"></p>    <p style="text-align:center">swift_tour_learning-swift.jpg</p>    <p>在 WWDC 2014 上 Apple Duang!!! 一声发布了 Swift 。在那次发布会上, Apple 向外界宣布了,自己其实是一家软件公司。</p>    <p>2015 年, Apple 又 Duang!!! 一声将 Swift 开源。这让 Swift 迅速攻占了服务器,这使 Swift 开发 Backend server 成为了可能( Vapor )。</p>    <p>初次接触 Swift,让我看到了 Scala、C#、ES 6 的影子,并且语法层面兼容 Objective C。first-class functions 特性让语言并不局限于 OO,让 Swift 具有函数式编程语言的表达力。 同时,Swift 作者 Chris Lattner 这位传奇人物的存在,让 Swift 成为值得长期投资的一门语言。</p>    <h2>变量</h2>    <p>Swift 中可以使用 var 和 let 直接定义 变量 或 常量 。</p>    <p>定义变量:</p>    <p>​</p>    <pre>  <code class="language-swift">var age = 20// 定义变量  let name = "Halo" // 定义常亮  age = 21</code></pre>    <p>声明类型:</p>    <p>上段代码看起来有些类似 javascript 若类型语言的特性,Swift 本质上还是强类型的语言,声明变量的时候,可以指定数据类型:</p>    <pre>  <code class="language-swift">let cash: Float = 1.25  let money: Double = 1.252525  let dollar: String = "USD"</code></pre>    <h2>使用 String</h2>    <p>对于字符串,Swift 简化了 Objective C NSString 的定义方式: @"" :</p>    <pre>  <code class="language-swift">let currencies = "AUD, " + dollar  let rmb = "1 \(dollar) is 6 RMB"  let formattedString = String(format: "%.2f \(dollar) is about 600 RMB", 100.0) // 100.00 USD is about 600 RMB</code></pre>    <p>\(variable) 是 Swift 为字符串模板提供的支持。不过 Swift 还是支持类似 ES 6 或者 Ruby 中多行字符串模板。多行字符串还是需要 + 号拼接:</p>    <pre>  <code class="language-swift">let introduceSwift = "We are excited by this new chapter in the story of Swift. " +      "After Apple unveiled the Swift programming language, it quickly became one of " +      "the fastest growing languages in history. Swift makes it easy to write software " +      "that is incredibly fast and safe by design. Now that Swift is open source, you can " +      "help make the best general purpose programming language available everywhere."</code></pre>    <h2>使用 tuple</h2>    <p>tuple 是 Swift 引入的一种新的数据类型,它可以方便支持方法的多返回值:</p>    <pre>  <code class="language-swift">let numbersTuple = (1, 100, 1000)      print("min: \(numbersTuple.0), max: \(numbersTuple.1), sum: \(numbersTuple.2)")    let numbersNamedTuple = (min: 1, max: 100, sum: 1000)      print("min: \(numbersNamedTuple.0), max: \(numbersNamedTuple.1), sum: \(numbersNamedTuple.2)")      print("min: \(numbersNamedTuple.min), max: \(numbersNamedTuple.max), sum: \(numbersNamedTuple.sum)")</code></pre>    <h2>Collections</h2>    <p>创建集合:</p>    <p>Swift 的集合类型主要还是 Array 和 Dictionary :</p>    <pre>  <code class="language-swift">var fruits = ["apple", "banana", "oranage"]  var fruitsPrice = [      "apple": 4.25,      "banana": 6.2  ]  print(fruitsPrice[fruits[1]]) // 6.2</code></pre>    <p>定义空集合:</p>    <pre>  <code class="language-swift">var emptyArray = [String]()  var emptyDictionary = [String: Float]()</code></pre>    <p>将已有集合设置为空时,可以用如下简写:</p>    <pre>  <code class="language-swift">fruits = []  fruitsPrice = [:]</code></pre>    <p>使用 for in 遍历集合:</p>    <pre>  <code class="language-swift">for score in [1,2,3,4,5,6] {      print(score * score * score)  }    for (key, val) in ["one": 1, "two": 2] {      print("\(val) is \(key)")  }</code></pre>    <h2>if else 和 Optional</h2>    <p>Swift 中新增一种类型 Optional,这个概念来自 Scala。 Optional 类似一个包装器,它可以包装一个数值,但是 Optional 可能返回 nil ,可能返回数据。多用于错误处理,通常跟 if else 连用:</p>    <p>声明 Optional:</p>    <pre>  <code class="language-swift">var optionalString: String? = nil  //print(optionalString!) // nil 取值会报错  print(optionalString == nil)    var optionalName: String? = "Jian"  print(optionalName!)</code></pre>    <p>String? 表示一个 String 类型的 Optional。只有 Optional 可以接受 nil 值。如果对一个 nil 的 Optional 取值会报错,一般取值前会对 Optional 做判断:</p>    <pre>  <code class="language-swift">var optionalString: String? = nil    if optionalString != nil {      let val = optionalString!  } else {      print("There is no value")  }</code></pre>    <p>if-else 简化 Optional 取值:</p>    <p>Swift 为上面这种方式提供一种简写:</p>    <pre>  <code class="language-swift">if let val = optionalString {      print("There is a value: \(val)")  } else {      print("There is no value")  }</code></pre>    <p>通常会将 if-else 和 Optional 这么使用:</p>    <pre>  <code class="language-swift">var optionalName: String? = "Jian"  print(optionalName!)    var greeting = "Hello!"    if let name = optionalName {      greeting = "Hello \(name)"  }</code></pre>    <p>Optional 默认值:</p>    <p>使用 ?? 可以为 Optional 提供默认值:</p>    <pre>  <code class="language-swift">let fullName: String = "Jian"  let nickName: String? = nil  let displayName = "\(nickName ?? fullName)"</code></pre>    <h2>switch</h2>    <p>Swift 中的 switch 强大很多,支持 String,多值匹配,条件匹配:</p>    <pre>  <code class="language-swift">let vegetable = "red pepper"    switch vegetable {  case "celery":      print("Add some raisins and make ants on a log.")  case "cucumber", "watercress":      print("Taht would make a good tea sandwich.")  case let x where x.hasSuffix("pepper"):      print("Is it a spicy \(x)?") // Is it a spicy red pepper?  default:      print("Everythink tasts good")  }</code></pre>    <h2>使用循环</h2>    <p>for in 循环</p>    <p>Swift 中的 for in 和 javascript 中的有点类似。使用 for in 便利 Dictionary:</p>    <pre>  <code class="language-swift">let numbersDict = [      "Prime": [2, 3, 5, 7, 11, 13],      "Fibonacci": [1, 1, 2, 3, 5, 8],      "Square": [1, 4, 9, 16, 25]  ]    var largest = 0    for (kind, numbers) in numbersDict {      for number in numbers {          number          if number > largest {              largest = number          }      }  }  print(largest) // 25</code></pre>    <p>使用 for in 遍历 Range:</p>    <pre>  <code class="language-swift">var total = 0  for i in 0..<4 {      total += i  }  print(total) // 6</code></pre>    <p>while 循环</p>    <p>一般语言都会提供 while 和 do {} while 循环。Swift 采用 while 和 repeat {} while :</p>    <pre>  <code class="language-swift">var n = 1  while n < 100 {      n += n  }  print(n) //128    var m = 1  repeat {      m += m  } while m < 100  print(m) // 128</code></pre>    <h2>Functions</h2>    <p>Swift 中的函数具有 javascript 和 objective c 的双重特征。并且函数在 Swift 中是一等公民(First-class type),具有高阶函数的特性。</p>    <p>定义函数</p>    <p>一般情况下,跟 Objective C 方法一样,需要给函数参数提供 Label:</p>    <pre>  <code class="language-swift">func greet(person: String, day: String) -> String {      return "Hello \(person), today is \(day)."  }  greet(person: "Jian", day: "Friday")</code></pre>    <p>使用 _ 表示省略 Label:</p>    <pre>  <code class="language-swift">func greet(_ person: String, on day: String) -> String {      return "Hello \(person), today is \(day)."  }  greet("Jian", on: "Friday")</code></pre>    <p>函数可以使用 tuple 返回多个值:</p>    <pre>  <code class="language-swift">func calcStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {      var min = scores[0]      var max = scores[0]      var sum = 0        for score in scores {          if score > max {              max = score          } else if score < min {              min = score          }            sum += score      }        return (min, max, sum)  }    let statistics = calcStatistics(scores: [5, 1, 100, 30, 90])  print(statistics.sum) // 226  print(statistics.2)   // 226</code></pre>    <p>无限参数:</p>    <pre>  <code class="language-swift">func sumOf(numbers: Int...) -> Int {      return numbers.reduce(0, +)  }  sumOf()                             // 0  sumOf(numbers: 1, 2, 3, 4, 10)      // 20</code></pre>    <p>使用 Int... 在函数的最后一个参数,表示后面可以接受无限个整数参数。</p>    <p>函数嵌套</p>    <pre>  <code class="language-swift">func returnFifteen() -> Int {      var y = 10      func add() { y += 5 }      add()      return y  }  returnFifteen() // 15</code></pre>    <p>高阶函数</p>    <p>高阶函数( high-order function ),是函数是编程的一个概念,高阶函数的特点:</p>    <ul>     <li>可以将函数当做返回值,即:可以使用函数创建函数</li>     <li>可以将函数当做参数接收</li>    </ul>    <p>使用函数创建另一个函数:</p>    <pre>  <code class="language-swift">func createIncrementer() -> ((Int) -> Int) {      func plusOne(number: Int) -> Int {          return 1 + number      }        return plusOne  }  let incrementer = createIncrementer()  incrementer(10)</code></pre>    <p>函数作为参数:</p>    <pre>  <code class="language-swift">func hasAnyMatches(_ list: [Int], matcher: (Int) -> Bool) -> Bool {      for item in list {          if matcher(item) {              return true          }      }        return false  }    func lessThanThen(number: Int) -> Bool {      return number < 10  }    hasAnyMatches([20, 10, 7, 12], matcher: lessThanThen)</code></pre>    <h2>Closure (闭包)</h2>    <p>Closure 可以理解匿名函数,在很多 Callback 和集合操作中使用:</p>    <pre>  <code class="language-swift">hasAnyMatches([20, 10, 7, 12]) { (item: Int) -> Bool in      item < 10  }  [20, 10, 7, 12].map { (item: Int) -> Int in      return 3 * item  }  [20, 10, 7, 12].map({ item in 3 * item })</code></pre>    <p>如果省略 () 后, Closure 是唯一的参数:</p>    <pre>  <code class="language-swift">let sortedNumbers = [20, 10, 7, 12].sorted { $0 > $1 }  print(sortedNumbers)</code></pre>    <h2>Objects and Classes</h2>    <p>定义和使用类:</p>    <pre>  <code class="language-swift">class Shape {      var numberOfSides = 0        func simpleDescription() -> String {          return "A shap with \(numberOfSides) sides."      }  }  let shape = Shape()  shape.numberOfSides = 10  shape.simpleDescription()</code></pre>    <p>使用继承:</p>    <pre>  <code class="language-swift">class NamedShape : Shape {      var name: String        init(name: String) {          self.name = name      }  }    // inherit and override  class Square: NamedShape {      var sideLength: Double        init(sideLength: Double, name: String) {          self.sideLength = sideLength          super.init(name: name)          numberOfSides = 4      }        func area() -> Double {          return sideLength * sideLength      }        override func simpleDescription() -> String {          return "A square with sides of length \(sideLength)"      }  }    let square = Square(sideLength: 10.0, name: "Jian's Square")  square.area()  square.simpleDescription()</code></pre>    <p>使用属性</p>    <p>Swift 中对属性的处理,有些像 C#。</p>    <p>使用 getter/setter</p>    <pre>  <code class="language-swift">class EquilateralTriangle: NamedShape {      var sideLength: Double = 0.0        init(sideLength: Double, name: String) {          self.sideLength = sideLength          super.init(name: name)          numberOfSides = 3      }        var perimeter: Double {          get {              return 3.0 * sideLength          }          set {              sideLength = newValue / 3.0          }      }        override func simpleDescription() -> String {          return "An equilateral triangle with sides of length \(sideLength)"      }  }  var triangle = EquilateralTriangle(sideLength: 3.1, name: "A triangle")  print(triangle.perimeter)           // 9.3    triangle.perimeter = 9.9  print(triangle.sideLength)          // 3.3</code></pre>    <p>使用 willSet:</p>    <pre>  <code class="language-swift">class TriangleAndSquare {      var triangle: EquilateralTriangle {          willSet {              square.sideLength = newValue.sideLength          }      }        var square: Square {          willSet {              triangle.sideLength = newValue.sideLength          }      }        init(size: Double, name: String) {          square = Square(sideLength: size, name: name)          triangle = EquilateralTriangle(sideLength: size, name: name)      }  }    var triangleAndSquare = TriangleAndSquare(size: 10, name: "other shape")  print(triangleAndSquare.square.sideLength)          // 10.0  print(triangleAndSquare.triangle.sideLength)        // 10.0    triangleAndSquare.square = Square(sideLength: 50, name: "Large square")  print(triangleAndSquare.triangle.sideLength)        // 50.0</code></pre>    <p>使用 willSet 保证 square 和 triangle 的 sideLength 始终相等。</p>    <p>使用 Optional 类型</p>    <p>使用 ?. 取值,当值为 nil 时返回 nil ,而不是报错。</p>    <pre>  <code class="language-swift">let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")  let sideLength = optionalSquare?.sideLength  let nilSquare: Square? = nil  let nilLength = nilSquare?.sideLength</code></pre>    <h2>Enumerations</h2>    <p>定义 enum 类型:</p>    <pre>  <code class="language-swift">enum Level: Int {      case Zero, First, Second  }  Level.Zero.rawValue  Level.First.rawValue</code></pre>    <p>enum 的 rawValue 默认从 0 开始,依次递增。</p>    <p>在 enum 中创建方法:</p>    <pre>  <code class="language-swift">enum Suit {      case spades, hearts, diamonds, clubs      func simpleDescription() -> String {          switch self {          case .spades:              return "spades"          case .hearts:              return "hearts"          case .diamonds:              return "diamonds"          case .clubs:              return "clubs"          }      }  }</code></pre>    <p>定义特性类型的 enum:</p>    <pre>  <code class="language-swift">enum Rank: Int {      case ace = 1      case two, three, four, five, six, seven, eight, nine, ten      case jack, queen, king        func simpleDescription() -> String {          switch self {          case .ace:              return "ace"          case .jack:              return "jack"          case .queen:              return "queen"          case .king:              return "king"          default:              return String(self.rawValue)          }      }  }  let ace = Rank.ace                      // ace  let aceRawValue = ace.rawValue          // 1</code></pre>    <p>enum Rank: Int 设置 enum 的 rawValue 为 Int 。我们也可以通过 rawValue 来创建 enum :</p>    <pre>  <code class="language-swift">if let convertedRank = Rank(rawValue: 3) {      let threeDescription = convertedRank.simpleDescription()        // 3  }</code></pre>    <p>复杂的 enum :</p>    <pre>  <code class="language-swift">enum ServerResponse {      case result(String, String)      case failure(String)  }    let success = ServerResponse.result("6:00 am", "8:00 pm")  let failure = ServerResponse.failure("Out of cheese")    switch success {  case let .result(sunrise, sunset):      print("Sunrise is at \(sunrise) and sunset is at \(sunset)") // Sunrise is at 6:00 am and sunset is at 8:00 pm  case let .failure(message):      print("Failure ... \(message)")  }</code></pre>    <h2>Structs</h2>    <pre>  <code class="language-swift">struct Card {      var rank: Rank      var suit: Suit        func simpleDescript() -> String {          return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"      }  }  let threeOfSpades = Card(rank: .three, suit: .spades)   // Card  print(threeOfSpades.simpleDescript())                   // The 3 of spades</code></pre>    <p>struct 和 class 最重要的区别是:</p>    <ul>     <li>struct 传递值,始终传递 copy</li>     <li>class 传递引用。</li>    </ul>    <h2>Protocol</h2>    <pre>  <code class="language-swift">protocol ExampleProtocol {      var simpleDescription: String { get }      mutating func adjust()  }</code></pre>    <p>Protocol 与 Java 中的 Interface 概念类似。在 Swift 中,class、struct、enum、extension 都可以实现 Protocol:</p>    <p>class 实现 protocol:</p>    <pre>  <code class="language-swift">class SimpleClass: ExampleProtocol {      var simpleDescription: String = "A simple class."      var moreProperty: Int = 315      func adjust() {          simpleDescription += " Now 100% adjusted"      }  }  var simpleClass = SimpleClass()  simpleClass.adjust()  print(simpleClass.simpleDescription)        // A simple class. Now 100% adjusted</code></pre>    <p>struct 实现 protocol:</p>    <pre>  <code class="language-swift">struct SimpleStructure: ExampleProtocol {      var simpleDescription: String = "A simple structure"      mutating func adjust() {          simpleDescription += " (adjusted) "      }  }    var simpleStruct = SimpleStructure()  simpleStruct.adjust()  print(simpleStruct.simpleDescription)</code></pre>    <p>mutating 修饰符表示,当前方法在 struct 中可以修改 struct 的值。</p>    <p>在 protocol 的应用中,可以使用 Java 中面向 Interface 编程:</p>    <pre>  <code class="language-swift">let protocolValue: ExampleProtocol = simpleStruct  print(protocolValue.simpleDescription)              // A simple structure (adjusted)</code></pre>    <h2>Extensions</h2>    <p>Swift 中的 extension 和 ruby 中的 Open Class 概念很像,在 ObjC 中是 Category 。它可以为已有类型添加新的特性:</p>    <pre>  <code class="language-swift">extension Int: ExampleProtocol {      var simpleDescription: String {          return "The number \(self)"      }        mutating func adjust() {          self += 10      }  }    print(7.simpleDescription)</code></pre>    <h2>Error Handling</h2>    <p>throws 异常</p>    <pre>  <code class="language-swift">enum PointerError: Error {      case outOfPaper      case noToner      case onFire  }    // throw error  func send(job: Int, toPointer printerName: String) throws -> String {      if printerName == "Never has toner" {          throw PointerError.noToner      }      return "Job sent"  }</code></pre>    <p>catch 和处理异常</p>    <p>对于具有 throws 声明的方法,需要使用 try 关键字调用,然后使用 do {} catch {} 包裹:</p>    <pre>  <code class="language-swift">do {      let pointerResp = try send(job: 1024, toPointer: "Never has toner")      print(pointerResp)  } catch { // catch all errors      print(error) // use error by default  }</code></pre>    <p>处理多个异常:</p>    <pre>  <code class="language-swift">do {      let pointerResponse = try send(job: 1024, toPointer: "Jian")      print(pointerResponse)      throw PointerError.onFire    } catch PointerError.onFire {      print("I'll just put shi over here, with the result of the fire.")      // I'll just put shi over here, with the result of the fire.  } catch let pointerError as PointerError {      print("Printer error: \(pointerError) .")  } catch {      print(error)  }</code></pre>    <p>通常 catch 多个 Error 时, catch 顺序需要从小异常,到范围更大的异常。</p>    <p>使用 try?</p>    <pre>  <code class="language-swift">// try? -> Optional  let pointerFailure = try? send(job: 1024, toPointer: "Never has toner")         // nil  let pointerSuccess = try? send(job: 2048, toPointer: "Good pointer")        // Job sent</code></pre>    <p>使用 defer</p>    <p>在方法 throws 时,会终端当前函数后续的代码执行,使用 defer 可以确保 defer 代码段中的代码在函数返回前始终被执行。这个概念有些像 Java 的 try {} catch {} finally {} 中的 finally :</p>    <pre>  <code class="language-swift">func ensureExecute() throws -> String {      defer {          print("Complete")      }        do {          try send(job: 1024, toPointer: "Never has toner")      } catch {          throw error      }        return "Executed"  }  let executed = try? ensureExecute()     // Complete</code></pre>    <h2>Generic</h2>    <p>Swift 开始支持泛型(Generic):</p>    <pre>  <code class="language-swift">enum OptionalValue<Wrapped> {      case none      case some(Wrapped)  }  var possibleInteger: OptionalValue<Int> = .none     // none  possibleInteger = .some(100)                        // some(100)</code></pre>    <p>使用 where 限定泛型的类型:</p>    <pre>  <code class="language-swift">func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool      where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {            for lhsItem in lhs {              for rhsItem in rhs {                  if lhsItem == rhsItem {                      return true                  }              }          }            return false  }  anyCommonElements([1,2,3,4,5], [5])</code></pre>    <p>where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element 限制 T 和 U 中的元素,必须实现 Equatable ,并且 T 和 U 中的元素是同一种类型。</p>    <h2> </h2>    <p> </p>    <p>来自:http://www.jianshu.com/p/3d8963cdb0b9</p>    <p> </p>