Swift3.0新特性和改動

前兩天的WWDC 2016上蘋果發了:Swift 3.0 Preview 1 Released!,此次更新了44個特性。有增刪一些語法得,有改動的,本身從Swift2和Xcode6開始學習Swift一直很喜歡這門語言。也老是看別人的東西,此次也是第一次主動嘗試翻譯一些文章,但願翻譯點東西方便別人學習Swift。持續更新。算法

英文原版的Github連接點這裏編程

下面正式開始逐條翻譯:swift

SE-0002: Removing currying func declaration syntax 移除了currying func,(譯者注:這個概念JavaScript和scala也有,scala裏叫:"柯里化"我剛看到這個單詞還覺得是納悶,怎麼和庫里名字同樣。這是比較廣泛的一個概念,我本身也不是十分清楚,可是有例子,例子仍是比較容易理解)。移除的緣由官方解釋說它增長了語言的複雜性,因此移除了。具體請看下面的例子。api

如下是對比代碼:數組

// 以前能夠這麼寫:
  func curried(x: Int)(y: String) -> Float {
    return Float(x) + Float(y)!
  }

  // 如今能夠改成:(譯者注:實際上是改爲改了用閉包實現)
  func curried(x: Int) -> (String) -> Float {
    return {(y: String) -> Float in
      return Float(x) + Float(y)!
    }
  }

SE-0003: Removing var from Function Parameters 移除了聲明函數的時候用var修飾形參,以區別在函數形參中var和inout。 關於這條改動蘋果官方說這個改動和剛開始的時候提的建議是不一致的,早先是要從這個refutable patterns(這個功能還不瞭解)移除var的,可是在mutation patterns裏這種東西用的不少了,蘋果官方決定不改這部分,而是把它從函數聲明中移除了。閉包

如下是對比代碼:編程語言

func doSomethingWithVar(var i: Int) {
  i = 2 // 此時i改變了可是調用者的值並無改變
}

func doSomethingWithInout(inout i: Int) {
  i = 2 // 這種用inout修飾的會把i的值會寫給調用者
}

// 下面的栗子可能更清楚一些
var x = 1
print(x) // 1

doSomething**WithVar**(x)
print(x) // 1

doSomething**WithInout**(&x)
print(x) // 2

函數形參中用inout修飾的參數若是改動會回寫給調用者,而var不會ide

SE-0004: Remove the ++ and -- operators 移除了++和--,官方的說法是:這是從C中帶來的,開發人員當時就這麼寫了,後來也沒有人留意這個狀況。可是如今他們注意到一些問題,請看下面的例子。函數

對比例子以下:oop

let a = ++x  // pre-increment  - +1以後再返回
let b = x++  // post-increment - +1以前就返回
let c = --x  // pre-decrement  - -1以後再返回
let d = x--  // post-decrement - -1以前就返回

蘋果的官方解釋說:你們總這麼用,可是不多有人真正關注到++在以前和以後的區別,容易弄混淆,因此移除了。固然這種操做符也是有好處的原文有對比有點和缺點。

SE-0005: Better Translation of Objective-C APIs Into Swift 這條主要是說將類C語言(原文是:「Clang」,包括OC,C和C++)的函數,方法,類型,屬性的名字導入轉換成Swift語言的時候更Swift一些。由於OC的設計語言的原則和Swift是不同的,蘋果會使用一些簡單的語言分析二者的不一樣,而後導入成Swift語言的時候將OC的代碼的命名改的更Swift一些。

SE-0006: Apply API Guidelines to the Standard Library 這條對如今的代碼影響比較大 Swift API Design Guidelines:Swift API的設計原則已經做爲Swift3的一部分在開發了,由於Swift標準庫多是程序裏用到的最多的API了。因此Swift標準庫API應該是遵照Swift API設計原則,因此開發人員review了整個Swift標準庫,作了一些改進使得他們更符合Swift API設計原則。

這條改動對2.x的代碼影響很是大,由於標準庫裏一些函數和變量名字都改了,一下列舉一部分方便你們理解這個改動:

一、不少地方用到的generator改爲了iterator,還有一個都是數組中的sort() => sorted(), sortInPlace() => sort() 二、不少協議中的的後綴Type都被移除了,好比: ``` 減號表示移除,加號是新增的 -public protocol SequenceType { ... } +public protocol Sequence { ... }

-public protocol CollectionType : ... { ... }
+public protocol Collection : ... { ... }
```

三、標準庫裏的靜態的屬性和枚舉的變量名都變成小寫的了 ``` public struct Float { - public static var NaN: Float + public static var nan: Float }

public enum FloatingPointClassification {
    - case QuietNaN
    + case quietNaN

    - case NegativeSubnormal
    + case negativeSubnormal

    - case NegativeZero
    + case negativeZero

```

四、一些Collection,Sequence,iterator適配器的初始化方法被移除了,推薦相關類的方法和算法函數來代替。就是移除了一些類的init()方法,推薦用其餘的方法,其中推薦方法的返回值和參數都沒變。

```
public struct LazyFilterIterator<Base : IteratorProtocol> : ... {
    - public init(
    - _ base: Base,
    - whereElementsSatisfy predicate: (Base.Element) -> Bool
    )
 }
// init 移除了,調用 `.lazy.filter` 代替.

 public struct RangeIterator<Element : ForwardIndex> : ... {
    - public init(_ bounds: Range<Element>)
    // init移除了,用 'generate()' 這個方法代替.
 }

 public struct ReverseCollection<Base : ...> : ... {
    - public init(_ base: Base)
    // Use the 'reverse()' method on the collection.
 }
```

五、還有幾個改動函數名字的我一併列舉了: reverse() => reversed() enumerate() => enumerated() SequenceType.minElement() => .min(), .maxElement() => .max() SE-0007: Remove C-style for-loops with conditions and incrementers 這條是說:把 for-loops 移除了,也就是這種for(val i = 0 ; i < 10 ; i++),推薦使用for in 文中說了一些歷史緣由,以及for-loops的好處和壞處,但總之是移除了。

SE-0008: Add a Lazy flatMap for Sequences of Optionals 這條是說:Swift標準庫裏有兩個flatMap來構造一個新的序列(Sequence 數組和集合的統稱)一種是調用的序列裏都是肯定值不帶Optional的,另一種是帶Optional的。可是能夠處理Optional類型的序列的flatMap沒有提供一個lazy方法,此次加上了。有點繞,具體看下面的栗子:

-------------------------------Swift 3.0以前-----------------------------
```
[1, 2, 3]
.flatMap { n in n..<5 } 
// [1, 2, 3, 4, 2, 3, 4, 3, 4]
這是第一種,沒有Optional的flatMap

(1...10)
.flatMap { n in n % 2 == 0 ? n/2 : nil }
// [1, 2, 3, 4, 5]
這是第二種,模擬出來的nil帶Optional的flatMap,可是隻有第一種有lazy的,第二種不帶。
```

-------------------------------Swift 3.0以後-----------------------------
增長了第二種flatMap的lazy實現(這種實現實際上是一個開發者提出來的,詳情[輸入連接說明](http://thread.gmane.org/gmane.comp.lang.swift.evolution/9365)),具體實現以下(原文裏有好幾種可用的實現方法):
```
// 基本上採用了那位網友的實現方法,用了一個map-filter-map鏈解決問題的。
extension LazySequenceType {
  @warn_unused_result
  public func flatMap<T>(transform: Elements.Generator.Element -> T?)
    -> LazyMapSequence<LazyFilterSequence<LazyMapSequence<Elements, T?>>, T> {
      return self
        .map(transform)
        .filter { opt in opt != nil }
        .map { notNil in notNil! } // filter後仍是Optinal類型的,顯式的解包一下。
  }
}
```

SE-00016: Add initializers to Int and UInt to convert from UnsafePointer and UnsafeMutablePointer 這條是說:原來UnsafePointer 和 UnsafeMutablePointer這兩個類裏面有init方法將其轉換成Int和Uint,可是Int和Uint裏卻沒有與之對應的轉換成UnsafePointer 和 UnsafeMutablePointer的init方法。這條對現有的代碼無任何影響。 代碼入下:

```
// 這些實現是基於ptrtoint_Word的內置函數
extension UInt {
  init<T>(bitPattern: UnsafePointer<T>) {
    self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
  }

  init<T>(bitPattern: UnsafeMutablePointer<T>) {
    self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
  }

  init(bitPattern: OpaquePointer) {
    self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
  }
}

extension Int {
  init<T>(bitPattern: UnsafePointer<T>) {
    self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
  }

  init<T>(bitPattern: UnsafeMutablePointer<T>) {
    self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
  }

  init(bitPattern: OpaquePointer) {
    self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
  }
}
```

這倆類我麼有用過,對C也不太熟悉,你們仍是看具體例子吧。可是蘋果的開發人員對此有個解釋爲啥要加這麼個方法:目前Swift缺少執行復雜的指針操做的能力,像檢查指針的範圍,給指針打標籤,指針作XOR操做。做爲一門系統編程語言,Swift應該可以能簡明直接的解決這些問題。另一些C語言的函數把intptr_t 和 uintptr_t做爲參數,可是Swift並不能直接調用這些函數,用戶須要用C語言對調用進行封裝。基於這些Swift決定增長以上init方法。

SE-00016: Change Unmanaged to use UnsafePointer 使用Unmanaged的地方要改爲用UnsafePointer了,這個改動也是和C語言api相關。

受影響的是如下兩個方法,這兩個方法是(這倆是將COpaquePointer和Unmanaged互相轉換的):

static func fromOpaque(value: COpaquePointer) -> Unmanaged<Instance>
func toOpaque() -> COpaquePointer

對現有的代碼的影響比較小:現存的用COpaquePointer調用Unmanaged的方法須要改爲用UnsafePointer。 COpaquePointer類型的變量能夠用一個可用的屬性來保留,以幫助轉換。具體用法入下:

@available(*, unavailable, message="use fromOpaque(value: UnsafeMutablePointer<Void>) instead")
@available(*, unavailable, message="use toOpaque() -> UnsafePointer<Void> instead")
相關文章
相關標籤/搜索