WWDC2016 Session 402 - What’s New in Swift

Swift 開(kāi)源已有6個(gè)月,開(kāi)源社區(qū)討論從未停歇過(guò)。Swift3 的目標(biāo)有以下4點(diǎn):

  1. 發(fā)展開(kāi)源社區(qū)
  2. 新平臺(tái)的可移植性(目前面向macOS和Ubuntu)
  3. 開(kāi)放更多基礎(chǔ)功能
  4. 持續(xù)優(yōu)化

前往Swift.org 了解更多。

Swift 在 Apple 中的普及率

目前公布的 Sierra macOS 系統(tǒng)中,大部分 Misson Control 都已經(jīng)使用 Swift 重寫(xiě),甚至 Accessibility 引擎完全使用了 Swift。

Ted Kremenek 以 Dock 為例,講述關(guān)于這個(gè)20萬(wàn)行代碼的應(yīng)用使用 Swift 重寫(xiě)后代碼量減少了15%之多,同時(shí)又增加了一些新功能。

GitHub 上的 Swift

眾所周知,Apple 開(kāi)源了 Swift,將項(xiàng)目托管到了 GitHub,項(xiàng)目有很多,譬如:swift、swift-evolution、swift-package-manager、swift-clang、swift-corelibs-libdispatch等等。不過(guò)實(shí)際可以劃分為三類:

  • Language:swift swift-evolution
  • Package Manager:swift-package-manager swift-llbuild
  • Core Libraries:swift-corelibs-xctest swift-corelibs-foundation swift-corelibs-libdispatch

更多請(qǐng)前往 GitHub 了解更多

如果你想要對(duì) swift 提出自己的想法或意見(jiàn),這意味著 evolution,Apple 十分歡迎開(kāi)發(fā)者踴躍參與,但是貌似國(guó)內(nèi)很多小伙伴不是很了解。大致流程是:

  • 郵件交流,講述你的想法,如何改動(dòng)。
  • 以 pr 方式提交你的建議。
  • 一旦接受,開(kāi)始review。
  • 郵件列表中review,比較正式。
  • 開(kāi)發(fā)團(tuán)隊(duì)決斷,打回or接受。

這里提供提案的列表,目前有102個(gè),有興趣可以看看,實(shí)時(shí)關(guān)注swift的動(dòng)態(tài)。

關(guān)于 swift 的改動(dòng)

Swift 3 的核心任務(wù)或者說(shuō)是目標(biāo)是提高兼容性,這對(duì)于跨平臺(tái)開(kāi)發(fā)至關(guān)重要。不僅是針對(duì) Swift3,亦包括 Swift4.0 版本。

下面根據(jù)視頻簡(jiǎn)單羅列一些:

命名準(zhǔn)則

API 設(shè)計(jì)準(zhǔn)則中重要幾點(diǎn):

  • 一目了然,而非過(guò)分簡(jiǎn)潔或冗余。
  • 突出重要信息
  • 省略冗余信息

更多請(qǐng)見(jiàn)Api-design-guidelines,貌似 Swift.gg 已經(jīng)有中文版了哦。

舉例:

swift 2

/// Swift.Array
array.appendContentsOf([2,3,4])
array.insert(1, atIndex: 0)

/// Foundation.NSURL
if url.fileURL {}
x = url.URLByAppendingPathComponent("file.txt")

swift3

/// Swift.Array
array.append(contentsOf: [2,3,4]) // 作為標(biāo)簽存在更加清晰
array.insert(1, at: 0) // index 沒(méi)有存在的意義

/// Foundation.NSURL
if url.isFileURL {} // 這里平常都會(huì)用到吧
x = url.appendingPathComponent("file.txt")// 都已經(jīng)是URL 何必加 URLBy前綴呢

很明顯改進(jìn)后調(diào)用意圖不變,但是精簡(jiǎn)了很多。

Objective-C API 和 Swift 橋接問(wèn)題

這里推薦 swift.gg 的SE-0005 更好的把 Objective-C APIs 轉(zhuǎn)換成 Swift 版本

簡(jiǎn)單舉例:

swift2

// oc
void CGContextFillPath(CGContextRef);//這是Core Graphic 畫(huà)圖庫(kù)中的函數(shù)!不是方法
// import 調(diào)用API變成如下 還是一個(gè)函數(shù)
func CGContextFillPath(_: CGContext)

swift3

// oc
void CGContextFillPath(CGContextRef)
           NS_SWIFT_NAME(CGContext.fillPath(self:));// 注意NS_SWIFT_NAME修飾符
// 對(duì) CGContext 擴(kuò)展
extension CGContext {
  func fillPath()
}

在說(shuō)說(shuō)泛型:

swift2

func findAnimals() {
  let request = NSFetchRequest(entityName:”Animal")
  guard let searchResults =
           try? context.executeFetchRequest(request) as! [Animal] {
    return
  }
  ...
  use(searchResults)
}

swift3

func findAnimals() {
  let request : NSFetchRequest<Animal> = Animal.fetchRequest 
  guard let searchResults = try? context.fetch(request) {
    return
  }
  ...
  use(searchResults)
}

旨在實(shí)例化一個(gè)對(duì)名為 Animalentity 請(qǐng)求,以前的寫(xiě)法是構(gòu)造函數(shù),而新的是上述這種方式,已驚呆。

// oc 
typedef NSString *NSNotificationName; // 對(duì) NSString 設(shè)置別名
const NSNotificationName NSUserDefaultsDidChangeNotification; // 變量A

// swift 導(dǎo)入
let NSUserDefaultsDidChangeNotification: String // oc變量A在swift中 實(shí)際就是String類型嘛

// 使用
center.addObserver(forName: NSUserDefaultsDidChangeNotification, ...) // 冗長(zhǎng)

swift3

typedef NSString *NSNotificationName NS_EXTENSIBLE_STRING_ENUM; // 注意修飾詞 變成了一個(gè)枚舉值.....
const NSNotificationName NSUserDefaultsDidChangeNotification;

// swift 導(dǎo)入
extension UserDefaults {
  class let didChangeNotification: NSNotification.Name
}

// 使用1
center.addObserver(forName: UserDefaults.didChangeNotification, ...)
// 使用2
center.addObserver(forName: .didChangeNotification, ...)

核心語(yǔ)言

函數(shù)參數(shù)標(biāo)簽的一致性

swift2

func myFunction(a: Int, b: Int, c: Int) { } 
myFunction(42, b: 57, c: 99)// 沒(méi)有 a 標(biāo)簽名

swift3

func myFunction(a: Int, b: Int, c: Int) { } 
myFunction(a: 42, b: 57, c: 99)

這個(gè)改動(dòng)應(yīng)該很早就提及過(guò)。如果你不是很愿意顯示參數(shù)標(biāo)簽,用 _ 忽略吧。

不知道大家對(duì) where 這個(gè)條件語(yǔ)句用的多不多,swift3 也做出了些許改動(dòng),主要是在放置位置上。

swift2

func anyCommon<T: Sequence, U: Sequence
               where T.Element: Equatable,
                     T.Element == U.Element
               >(lhs: T, rhs: U) -> Bool {}

注意我們的函數(shù)名和參數(shù)列表之間摻雜了太多語(yǔ)句了!

swift3

func anyCommon<T: Sequence, U: Sequence>(lhs: T, rhs: U) -> Bool 
          where T.Element: Equatable, T.Element == U.Element {}

在我們寫(xiě)完函數(shù)定義之后再寫(xiě)限制條件 where。很nice!

再來(lái)看看對(duì)未使用變量的處理

swift2

func plusOne(_ a: Int) -> Int {
  return a+1
}
plusOne(x)// 發(fā)出??警告,因?yàn)檫@個(gè)函數(shù)是有返回值

swift3

@discardableResult
func plusOne(_ a: Int) -> Int {
  print(a)     // side effect!
  return a+1
}
plusOne(x)
_ = plusOne(x)

注意@discardableResult 修飾符。

Swift3 移除的特性

移除東西可能讓你惶恐不安,但是這也是蘋(píng)果深思熟慮,權(quán)衡眾多開(kāi)發(fā)者提出的意見(jiàn)之后做出的決定。目的有三:

  • 致力于簡(jiǎn)化語(yǔ)言
  • 減少代碼上手難度
  • 向其他語(yǔ)言學(xué)習(xí),取其精華,去其糟粕

目前有哪些移除了的呢?

  • SE-0002 Currying func declaration syntax
  • SE-0003 函數(shù)參數(shù)列表中的 var
  • SE-0004 ++ 和 -- 運(yùn)算符
  • SE-0007 C 語(yǔ)言中的 for 循環(huán)

又有哪些新加入的呢?

  • SE-0025 加入 fileprivate 作用域范圍,咱們用的比較多的是 public private
  • SE-0043 case 標(biāo)簽的值綁定操作
  • SE-0048 泛型別名,貌似是associatedType

其他還有 SE-0062 SE-0064 SE-0068 SE-0075 SE-0092,不妨去 GitHub 上一睹為快吧。

修改又有哪些呢?

  • SE-0028 #file 替換了 FILE
  • SE-0031 inout 變成了類型的一部分
  • SE-0040 屬性語(yǔ)法: :替換=
  • SE-0049 @noescape@autoclosure 可以類型屬性
  • SE-0060 dynamicType 不再是屬性 而是運(yùn)算符。

類型系統(tǒng)的改變

先看一則 swift2 的例子:

let ptr : UnsafeMutablePointer<Int> = nil
if ptr != nil {
   ptr.memory = 42
}

而在swift3 中則是這樣干

let ptr : UnsafeMutablePointer<Int>? = nil 
ptr?.memory = 42

Imported C pointers in APIs obey _Nullable and _Null_unspecified
Consistency: nil is dedicated to Optional and ImplicitlyUnwrappedOptional

隱式解包可選類型(IUO Implicitly Unwrapped OptionaL)

swift2 中類型系統(tǒng)是這么推斷的:

func f(value : Int!) {
  let x = value + 1  // x: Int - 強(qiáng)制解包的結(jié)果
  let y = value      // y: Int!
  let array = [value, 42] // [Int], [Int!], [Int?], [Any]... 它無(wú)法推斷類型了 因?yàn)樗恢纘到底是有值呢還是nil呢
   use(array) //Cannot convert value of type ‘[Int!]’ to argument type
}

swift3 中類型系統(tǒng)就聰明很多了:

func f(value : Int!) {
  let x = value + 1  // x: Int - 強(qiáng)制解包的結(jié)果
  let y = value      // y: Int?
  let array = [value, 42] // [Int?], 
   use(array) 
}

浮點(diǎn)數(shù)和數(shù)字

直接上代碼:

/// swift2
let v = 2 * Float(M_PI)
return x * CGFloat(M_PI) / 180

/// swift3
let v = 2 * Float.pi
return x * CGFloat.pi / 180
return x * .pi / 180      // amazing!

更多

之后是關(guān)于 Swift Tools 的簡(jiǎn)單介紹,基本就是說(shuō)提升了多少性能,提供了swift2.2->swift2.3 swift2.2->swift2.3的轉(zhuǎn)換方式,可以選擇編譯優(yōu)化,速度更快,以及提示更加智能。這里不一一稱述。基本來(lái)看這個(gè)視頻只不過(guò)是概括性地講了下改動(dòng),沒(méi)有具體講到某個(gè)細(xì)節(jié)。所以嘍,只能作為開(kāi)胃菜吃著先,更多請(qǐng)見(jiàn)專題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容