WWDC 2015 - Session 106 - What's New In Swift2.0

大綱如下:

  • Fundamentals
  • Pattern Matching
  • Availability Checking
  • Protocol Extensions
  • Error Handling

Fundamentals

枚舉的反射

Swift1.2 :

enum Animals{
  case Dog, Cat, Troll, Dragon
}
let a = Animals.Dragon
print(a) //打印 (Enum Value)

Swift2. 0:

enum Animals{
  case Dog, Cat, Troll, Dragon
}
let a = Animals.Dragon
print(a) //打印 (Animals.Dragon)

調(diào)試過程中更直觀地顯示數(shù)據(jù)慧耍。

枚舉中的關(guān)聯(lián)值

Either:兩者選其一未辆,非此即彼的意思拉背。

這里構(gòu)造一個(gè) Either 枚舉断箫,且綁定 T1 和 T2 兩個(gè)泛型。Either枚舉有兩種情況:要么就是First澳淑,關(guān)聯(lián)值為 T1 類型比原;要么就是 Second ,關(guān)聯(lián)值為 T2 類型杠巡。想法很nice量窘,但是現(xiàn)實(shí)很殘酷,swift1.2中無法編譯通過忽孽,往往解決方法是自己構(gòu)造一個(gè)Box類绑改。

swift1.2 :

enum Either<T1,T2>{
  case First(T1)
  case Second(T2)
}
// swift1.2中直接報(bào)錯(cuò)

swift2.0 :

enum Either<T1,T2>{
  case First(T1)
  case Second(T2)
}
// 完美執(zhí)行

枚舉中的遞歸

swift1.2 中不允許采用遞歸,所以使用以下方式編譯報(bào)錯(cuò):

swift1.2 :

enum Tree<T>{
  case Leaf(T)
  case Node(Tree,Tree)
}
// 編譯器報(bào)錯(cuò)兄一,通過解決方式是自定義一個(gè)Box類

swift2.0 :

enum Tree<T>{
  case Leaf(T)
  indirect case Node(Tree,Tree)
  //在使用遞歸枚舉用例的地方使用修飾符 indirect 
}

repeat-while 替換 do-whi2

可能是因?yàn)橐肓?do-catch 語句厘线,為了避免混淆,所以將其改成了 repeat-while 聲明出革,感覺有一定意義吧造壮。

Option Sets

Swift1 中討論最多的就是使用位掩碼(bit mask)來實(shí)現(xiàn),學(xué)過C語言的朋友應(yīng)該再熟悉不過骂束。

swift1 :

// 設(shè)置動(dòng)畫選項(xiàng)時(shí)如此聲明耳璧,表示該動(dòng)畫具有 重復(fù)、漸進(jìn)漸出以及卷曲動(dòng)畫 三個(gè)屬性
viewAnimationOptions = .Repeat | .CurveEaseIn | .TransitionCurlUp

但是往往會(huì)造成誤解:

viewAnimationOptions = .Repeat | .CurveEaseIn | .TransitionCurlUp
viewAnimationOptions = nil
if viewAnimationOptions & .TransitionCurlUp != nil {}

采用與(&)展箱、或(|)操作來進(jìn)行結(jié)合旨枯,美名其曰是對集合進(jìn)行操作,實(shí)際不過是C語言的位操作罷了混驰。甚至類型上也顯得很牽強(qiáng)攀隔,要知道 options 是一個(gè)位掩碼值,做一個(gè)與(&)操作后竟然可以等于nil(恰當(dāng)?shù)靥幚響?yīng)該為一個(gè)空集合栖榨,不是嗎昆汹?)。

swift2.0 :

// 采用中括號(hào)[]來包括婴栽,讓其看起來是對集合進(jìn)行操作满粗,倘若沒有元素,即[]空集合 而非無值nil!
viewAnimationOptions = [.Repeat, .CurveEaseIn, .TransitionCurlUp]
viewAnimationOptions = []
// contain操作就是簡單.TransitionCurlUp 是否包含于集合中 很形象愚争!
if viewAnimationOptions.contains(.TransitionCurlUp) {

自定義一個(gè)可選集合:

struct MyFontStyle : OptionSetType {
// 一定要有rawValue
let rawValue : Int
static let Bold = MyFontStyle(rawValue: 1)
static let Italic = MyFontStyle(rawValue: 2)
static let Underline = MyFontStyle(rawValue: 4)
static let Strikethrough = MyFontStyle(rawValue: 8)
}
// style 是MyFontStyle類型 本例構(gòu)造了一個(gè)集合
myFont.style = []
myFont.style = [.Underline]
myFont.style = [.Bold, .Italic]
if myFont.style.contains(.StrikeThrough) {}

更多請見我寫的這篇文章[Swift2.0系列]OptionSetType使用

函數(shù)和方法

swift1.2 :

// 這里的save是全局函數(shù)(function)
func save(name: String, encrypt: Bool) { ... }
// 類中的save是方法(method)
class Widget {
  func save(name: String, encrypt: Bool) { ... }
// 調(diào)用全局函數(shù) 和 類方法 
save("thing", false)
widget.save("thing", encrypt: false)

注意調(diào)用函數(shù)和方法的標(biāo)簽映皆,函數(shù)是沒有任何外部標(biāo)簽的挤聘;而方法除了第一個(gè)沒有外部標(biāo)簽,從第二個(gè)開始都帶標(biāo)簽劫扒。

swift2.0為了和oc統(tǒng)一檬洞,現(xiàn)在函數(shù)也是從第二個(gè)參數(shù)開始默認(rèn)給定外部標(biāo)簽。
swift2.0 :

func save(name: String, encrypt: Bool) { ... }
class Widget {
func save(name: String, encrypt: Bool) { ... } 
// 注意這里 函數(shù)也是帶標(biāo)簽了
save("thing", encrypt: false)
widget.save("thing", encrypt: false)

你可能好奇為什么第一個(gè)參數(shù)沒有外部標(biāo)簽的沟饥,因?yàn)榫幾g器自動(dòng)用下劃線_替換掉了第一個(gè)參數(shù)的外部標(biāo)簽,表示省略外部標(biāo)簽湾戳,在調(diào)用時(shí)是不會(huì)顯示出來的贤旷,就像這樣:

// 注意_ 和 name之間是有空格的。 _表示忽略外部標(biāo)簽砾脑, name表示函數(shù)內(nèi)部使用參數(shù)標(biāo)簽
// 而encrypt 默認(rèn)外部標(biāo)簽和內(nèi)部標(biāo)簽是為同一個(gè)幼驶,即encrypt
func save(_ name: String, encrypt: Bool)

// 還可以這么寫
func save(_ name: String,encrypt encrypt: Bool)
// 顯然寫兩個(gè)encrypt 毫無意義,除非你想自定義外部參數(shù)標(biāo)簽名稱

// 想要第一個(gè)參數(shù)也具有外部參數(shù)標(biāo)簽名韧衣,可以這么干
func save(externalName name: String,encrypt encrypt: Bool)

關(guān)于Diagnostics

swift2.0中對警告和錯(cuò)誤更為敏感和友好盅藻,不像swift1.2中模糊不清的錯(cuò)誤信息,而是“一針見血”畅铭,方便你“對癥下藥”氏淑!當(dāng)然swift2.0還新增了一些其他有用的經(jīng)過,譬如變量聲明卻沒有使用硕噩,或者變量僅作為常量即可假残,無須使用var關(guān)鍵字聲明為變量等等

Pattern Matching

**swift1.0 **很容易出現(xiàn)金字塔“鞭尸”的情況:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let dest = segue.destinationViewController as? BlogViewController
        if let blogIndex = tableView.indexPathForSelectedRow()?.row {
            if segue.identifier == blogSegueIdentifier {
                    dest.blogName = swiftBlogs[blogIndex]
                    ...
                    ...
            }
        }
    }
}

swift1.2 中我們可以采用條件符合的寫法,但是也不盡如意:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // 注意我們把三個(gè)條件整合成了一個(gè)if語句 但是還是逃脫不了被鞭尸
    if let dest = segue.destinationViewController as? BlogViewController
       let blogIndex = tableView.indexPathForSelectedRow()?.row
       where segue.identifier == blogSegueIdentifier {
            dest.blogName = swiftBlogs[blogIndex]
            ...
            ...
    }
}

再舉個(gè)Json解析的例子:

// 返回Either枚舉值 要么就是有值為.First(Person) 要么沒有值.Second(String)
func process(json: AnyObject) -> Either<Person,String> { 
// 還有一點(diǎn)值得注意 我們聲明的name 和 year 都是可選類型值 所以都是需要解包的
let name: String? = json["name"] as? String
if name == nil {
return .Second("missing name")
}
let year: Int? = json["year"] as? Int
if year == nil {
    return .Second("missing year")
}
let person = processPerson(name!, year!)// 解包
return .First(person)

顯然解包行為的代碼令人無法直視炉擅,所以嘍你可能會(huì)在聲明name 和 year就直接采用隱式可選類型辉懒,即使用String!Int!來干,只能說治標(biāo)不治本吧谍失。ps:記住顯示可選類型和隱式可選類型都是可選類型眶俩,意味著它們都有值不存在的情況,即nil快鱼;區(qū)別在于顯示可選類型要解包颠印,隱式可選類型的解包由編譯器幫你完成,換句話說你不用每次都使用!來解包拉攒巍,但是這樣造成的嚴(yán)重后果是倘若值為nil了嗽仪,那么程序就crash嘍,所以且碼且謹(jǐn)慎柒莉。

swift2.0 引入了guard聲明闻坚,意為警衛(wèi),充當(dāng)一個(gè)保護(hù)者兢孝,只有條件滿足時(shí)才可以執(zhí)行下面的程序窿凤;倘若不滿足仅偎,就必須提前突出嘍!你可以使用return break 等關(guān)鍵字雳殊,當(dāng)然也可以使用no-return 方式橘沥,譬如assert exception等等。

// 現(xiàn)在是不是簡潔很多了 值得一提的是 name year 的作用域是整個(gè)函數(shù)
// 而if-let 中的解包數(shù)據(jù)作用域只能是if作用域
func process(json: AnyObject) -> Either<Person,String> {
    guard let name = json["name"] as? String,
          let year = json["year"] as? Int else
        return .Second(“bad input”)
    }
    let person = processPerson(name, year)
    return .First(person)
}

再來談?wù)?switch 語句夯秃,我很喜歡swift中的switch用法座咆,可以使用符合條件操作等,但是有一點(diǎn)我也很討厭仓洼,當(dāng)我想要匹配的條件僅有一個(gè)的時(shí)候介陶,竟然還要寫switch(){//一堆東西},就像下面這樣:

// 根據(jù) bar() 方法返回值進(jìn)行switch匹配 執(zhí)行對應(yīng)操作
switch bar() {
case .MyEnumCase(let value):where value != 42:
  doThing(value)
default: break
}

swift2.0 新增匹配方式:

if case .MyEnumCase(let value) = bar() where value != 42 {
    doThing(value)
}

for-in中的匹配

swift1.2 前你是否遇到過這種情況:

// for-in 每一次循環(huán)都要執(zhí)行 value != ""的判斷 是否令你不爽
for value in mySequence {
    if value != "" {
        doThing(value)
    }
}

你有考慮過這么干嗎:

for value in mySequence where value != "" {
    doThing(value)
}

假設(shè) mySequence 是一個(gè)枚舉序列呢色建?哺呜?? 難道你要在for-in中每一個(gè)循環(huán)執(zhí)行一次switch匹配嗎箕戳? Swift2.0中對這些say goodbye 吧某残!

for case .MyEnumCase(let value) in enumValues {
    doThing(value)
}

Availability Checking

請見這篇文章:
[Swift2.0系列]API可用性檢查(譯)

Protocol Extensions

給已實(shí)現(xiàn)的類型進(jìn)行Extension 想必很多開發(fā)者都嘗試過,譬如為Array擴(kuò)展一個(gè)countIf方法:

extension Array{
    func countIf(match:Element -> Bool) -> Int{
        var n = 0
        for value in self{
            if match(value){ n++}
        }
        return n
    }
}

這種做法很常見陵吸,但你要知道并不是只有Array適用countIf方法的玻墅,其他序列同樣適用!所以嘍我們會(huì)聲明一個(gè)全局函數(shù)專門對傳入的序列進(jìn)行處理:

func countIf<T:CollectionType>(collection:T,
    match:T.Generator.Element -> Bool) -> Int{
        var n = 0
        // WWDC pdf 為 for value in self 不知是否錯(cuò)誤 我改為 collection
        for value in collection{
            if match(value){ n++}
        }
        return n
}

但是通過全局函數(shù)來處理指定隊(duì)列可能會(huì)讓初學(xué)者很迷茫走越,他怎么知道有filter map這些函數(shù)呢椭豫?事實(shí)上swift1.0就是那么干的! 當(dāng)時(shí)用得相當(dāng)不爽旨指。

// 這種方式糟透了赏酥!
let x = filter(map(numbers) { $0 * 3 }) { $0 >= 0 }

swift2.0 :

let x = numbers.map { $0 * 3 }.filter { $0 >= 0 }

我們所要做的是對CollectionType協(xié)議進(jìn)行Extension,即為該協(xié)議實(shí)現(xiàn)默認(rèn)方法:

extension CollectionType {
func countIf(match: Element -> Bool) -> Int {
    var n = 0
    for value in self {
        if match(value) { n++ }
    }
    return n 
  }
}

當(dāng)然你可以在Array中覆蓋次默認(rèn)實(shí)現(xiàn)谆构,而采用自定義實(shí)現(xiàn)裸扶。

請見這篇文章:
[Swift2.0系列]Protocol Extensions 基礎(chǔ)用法和實(shí)戰(zhàn)(初稿)

Error Handling

請見我寫的這篇文章:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搬素,隨后出現(xiàn)的幾起案子呵晨,更是在濱河造成了極大的恐慌,老刑警劉巖熬尺,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摸屠,死亡現(xiàn)場離奇詭異,居然都是意外死亡粱哼,警方通過查閱死者的電腦和手機(jī)季二,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人胯舷,你說我怎么就攤上這事刻蚯。” “怎么了桑嘶?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵炊汹,是天一觀的道長。 經(jīng)常有香客問我逃顶,道長讨便,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任口蝠,我火速辦了婚禮器钟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘妙蔗。我一直安慰自己,他們只是感情好疆瑰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布眉反。 她就那樣靜靜地躺著,像睡著了一般穆役。 火紅的嫁衣襯著肌膚如雪寸五。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天耿币,我揣著相機(jī)與錄音梳杏,去河邊找鬼。 笑死淹接,一個(gè)胖子當(dāng)著我的面吹牛十性,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播塑悼,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼劲适,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了厢蒜?” 一聲冷哼從身側(cè)響起霞势,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斑鸦,沒想到半個(gè)月后愕贡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巷屿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年固以,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攒庵。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘴纺,死狀恐怖败晴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情栽渴,我是刑警寧澤尖坤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站闲擦,受9級(jí)特大地震影響慢味,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜墅冷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一纯路、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寞忿,春花似錦驰唬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至霹抛,卻和暖如春搓逾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杯拐。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工霞篡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人端逼。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓朗兵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親裳食。 傳聞我的和親對象是個(gè)殘疾皇子矛市,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

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