Swift之旅_Language Guide3

趁著五一放假又看了幾節(jié)官方文檔,順便記錄一下碰到的知識點伞芹。


Initialization

這一小節(jié)主要講解的是Swift中的初始化可柿,非常的長,差點沒勇氣看下去绊寻。

  • Setting Initial Values for Stored Properties

Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an indeterminate state.

類和結(jié)構(gòu)體在被創(chuàng)建的同時必須將全部的存儲屬性設(shè)置一個合適的值花墩。存儲的屬性不能以不確定的狀態(tài)保留。

Assigning Constant Properties During Initialization
You can assign a value to a constant property at any point during initialization, as long as it is set to a definite value by the time initialization finishes. Once a constant property is assigned a value, it can’t be further modified.

你可以給一個常量分配值在初始化過程中澄步,只要在初始化完成時將其設(shè)置為一定值即可冰蘑。一旦常量被分配了一個值,它不能被進(jìn)一步修改村缸。
之前還不知道常量可以在初始化方法中賦值祠肥,以為let修飾的變量就是不能賦值的。

class Person {
    let sex: String
    var age: Int?
    init(sex: String, age: Int) {
        self.sex = sex
        //Ps:可選類型可以不用在初始化方法中分配值王凑。因為它默認(rèn)分配了一個nil給它搪柑。
    }
}
  • Memberwise Initializers for Structure Types

這個之前貌似提到過,如果沒有自定義過初始化方法索烹,結(jié)構(gòu)體默認(rèn)會提供一個用來給每個結(jié)構(gòu)體成員分配一個值工碾。

struct Size {
    var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
  • Designated Initializers and Convenience Initializers

指定構(gòu)造器與便利構(gòu)造器。簡單的來說就是百姓,指定構(gòu)造器是必須的渊额,一個類必須至少有一個指定構(gòu)造器,而便利構(gòu)造器不是必須的垒拢,是為了更快捷的初始化類或者在意圖上更清晰旬迹。語法如下:
指定構(gòu)造器:

init(<#parameters#>) {
    <#statements#>
}

便利構(gòu)造器:

convenience init(<#parameters#>) {
    <#statements#>
}
  • Initializer Delegation for Class Types

To simplify the relationships between designated and convenience initializers, Swift applies the following three rules for delegation calls between initializers:

為了區(qū)別指定與便利構(gòu)再去,Swift提供了以下三個規(guī)則:
1.一個指定構(gòu)造器必須調(diào)用它的直接父類的指定構(gòu)造器求类。
2.一個便利構(gòu)造器必須調(diào)用同一個類的其他構(gòu)造器奔垦。
3.一個便利構(gòu)造器最終必須調(diào)用一個指定構(gòu)造器。

文檔上有一張圖片比較清楚的表達(dá)了指定構(gòu)造器與便利構(gòu)造器之間的聯(lián)系:(個人覺得其實這樣做的原因就是為了能夠保證這個類的每一個屬性包括繼承自父類的屬性都能夠保證在初始化的時候被分配一個值)
  • Initializer Inheritance and Overriding

Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that is not fully or correctly initialized.

Swift與OC不同尸疆,Swift不會默認(rèn)繼承父類的初始化方法椿猎。

  • Failable Initializers

可失敗的構(gòu)造器,可以在init后加上?表示這個構(gòu)造方法可能會失敗寿弱,失敗時可以返回nil犯眠。

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}
let anonymousCreature = Animal(species: "")
// anonymousCreature is of type Animal?, not Animal
 
if anonymousCreature == nil {
    print("The anonymous creature could not be initialized")
}
// Prints "The anonymous creature could not be initialized"
  • Required Initializers

Write the required modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer:

required修飾符表明這個類的所有子類必須實現(xiàn)這個構(gòu)造器。貌似以前重寫類初始化方法的時候xcode總是讓我寫上這樣一段代碼

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

今天碰到就查了一下相關(guān)的資料症革,是這樣說的筐咧,創(chuàng)建一個繼承自遵循NSCoding協(xié)議類的時候,如果你定義了指定構(gòu)造器或者重寫了父類的指定構(gòu)造器,那么就必須實現(xiàn)required init?(coder aDecoder: NSCoder)量蕊。fatalError("init(coder:) has not been implemented")最好改成super.init(coder: aDecoder)铺罢,否則程序有些情況下會被fatalError函數(shù)終止掉app并打印。
所以我也試了一下危融,不去寫指定構(gòu)造器或者重寫父類指定構(gòu)造器的時候畏铆,不去實現(xiàn)require修飾的構(gòu)造器是不會報錯,應(yīng)該是自動繼承了吉殃。

class Person {
    required init() {
    }
}
class Student: Person {
}

但是required init?(coder aDecoder: NSCoder)這個構(gòu)造器是用來干啥的應(yīng)該在這個構(gòu)造器里做些什么還沒有找到講的很好的資料辞居,只知道它是NSCoding協(xié)議定義的,如果有大神了解求告知蛋勺。

  • Setting a Default Property Value with a Closure or Function

用閉包或函數(shù)設(shè)置默認(rèn)屬性值

class SomeClass {
    let someProperty: SomeType = {
        // create a default value for someProperty inside this closure
        // someValue must be of the same type as SomeType
        return someValue
    }()
}

應(yīng)該是用于類似UIView這樣的初始化后需要設(shè)置一些屬性的類瓦灶、結(jié)構(gòu)或者枚舉。


Deinitialization

這一小節(jié)主要講解的是Swift中的析構(gòu)函數(shù)抱完。只有類中有析構(gòu)函數(shù)贼陶。你不能主動去調(diào)用析構(gòu)函數(shù),在arc中實例對象內(nèi)存會自動釋放巧娱,析構(gòu)函數(shù)也會被自動調(diào)用碉怔。

Class definitions can have at most one deinitializer per class. The deinitializer does not take any parameters and is written without parentheses:

每個類最多有一個析構(gòu)函數(shù)。并且析構(gòu)函數(shù)沒有參數(shù)禁添,也沒有圓括號:

deinit {
    // perform the deinitialization
}

之前碰到過因為block沒用好導(dǎo)致析構(gòu)函數(shù)沒有執(zhí)行撮胧,也就是實例對象沒有釋放成功,后來block中加上[weak self]之后能夠成功執(zhí)行老翘,所以析構(gòu)函數(shù)也可以用來驗證對象有沒有成功釋放吧芹啥。


Optional Chaining

這一小節(jié)主要講解的是Swift中的可選鏈。之前沒聽說這個概念铺峭,也不知道是不是該叫可選鏈= =墓怀,其實在平時開發(fā)中一直有用到。

class Person {
    var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
}
let john = Person()
let roomCount = john.residence!.numberOfRooms

這里的john.residence!.numberOfRooms就用到了卫键,因為Person中的residence是可選類型的傀履,在這里是nil,所以這句代碼會引發(fā)崩潰莉炉,安全的寫法是john.residence?.numberOfRooms啤呼,這樣john.residence是nil的時候會面就不會繼續(xù)執(zhí)行。

  • Calling Methods Through Optional Chaining

這里提到了通過可選鏈去調(diào)用方法呢袱,可選鏈調(diào)用方法沒啥奇怪的,但是這里有提到翅敌,當(dāng)你通過一個可選類型去調(diào)用方法的時候羞福,方法的返回值會被包上可選,如Void會變成Void?, Int會變成Int?

class Person {
    var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
    func printNumberOfRooms() {
        print("The number of rooms is \(numberOfRooms)")
    }
    func test() -> Int {
        return 100
    }
}
let john = Person()
print(john.residence?.printNumberOfRooms())
//打印 nil
john.residence = Residence()
print(john.residence?.test())
//打印 Optional(100)

Error Handling

這一小節(jié)主要講解的是Swift中的異常蚯涮。

  • Representing and Throwing Errors

通常Swift中的錯誤都是用一個枚舉類型并且遵循Error這個空協(xié)議來表示的治专,定義一個錯誤類型和拋出錯誤如下:

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}
throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

中間一串都是講的異常的用法卖陵,個人感覺沒啥難點,后面有提到另一種用法

  • Representing and Throwing Errors

可以在try后面加一個?张峰,try?,其實這也符合Swift語法的特性泪蔫,加上?之后如果throw一個error,后面表達(dá)式的值則為nil喘批。如下面代碼x與y做的事情其實一樣:

func someThrowingFunction() throws -> Int {
    // ...
}
let x = try? someThrowingFunction()
 
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}
  • Disabling Error Propagation

有?自然有!與之對應(yīng)撩荣,如果你肯定這個方法不會拋出異常,可以在try后面加上!饶深,這樣就不需要去catch錯誤餐曹,但是如果拋出了異常則會崩潰。

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
  • Specifying Cleanup Actions

defer敌厘,這個在之前也提到過台猴,defer代碼塊中的代碼是在一個方法return之后再調(diào)用的,無論函數(shù)是否拋出錯誤,都執(zhí)行該代碼俱两。不過這里有補(bǔ)充一個知識點饱狂,就是函數(shù)中的第一個defer最后調(diào)用,第二個倒數(shù)第二個調(diào)用宪彩,以此類推休讳,最后的一個defer則是第一個調(diào)用:

func test() {
    defer {
        print("1")
    }
    defer {
        print("2")
    }
    defer {
        print("3")
    }
    print("函數(shù)執(zhí)行完畢!")
}
test()
//函數(shù)執(zhí)行完畢!
//3
//2
//1

Type Casting

這一小節(jié)主要講解的是Swift中類型轉(zhuǎn)換。
前半截主要是講了is as的用法毯焕,感覺沒啥特別的知識點,翻到最后算是找到一個以前不知道的衍腥。

  • Type Casting for Any and AnyObject

Any can represent an instance of any type at all, including function types.
AnyObject can represent an instance of any class type.

之前也一直不知道Any和AnyObject的區(qū)別,看了文檔才發(fā)現(xiàn)原來Any是可以代表任何類型的實例纳猫,包括函數(shù)類型婆咸,而AnyObject則是表示任何類的實例對象。


Nested Types

這一小節(jié)主要講解的是Swift中的嵌套類型芜辕,就是講在結(jié)構(gòu)體尚骄、類和枚舉中定義結(jié)構(gòu)體、類和枚舉侵续,沒啥可講的倔丈,就是有一個注意點,在結(jié)構(gòu)體状蜗、類或枚中嵌套的結(jié)構(gòu)體需五、類或枚舉,在外部需要使用的時候需要在前面加上嵌套的類型轧坎,說著有點繞宏邮,直接看代碼:

class Person: NSObject {
    enum Sex {
        case Man
        case Woman
    }  
}
let sex = Person.Sex.Man

Extensions

這一小節(jié)主要講解的是Swift中的擴(kuò)展。Extensions類似Objective-C中的categories,可以給一個類蜜氨、結(jié)構(gòu)體械筛、枚舉或者協(xié)議增加新的方法。
Swift中的Extensions有以下功能:
1.添加計算實例屬性和計算類型屬性
2.定義實例方法和類方法
3.提供新的初始化方法
4.定義下標(biāo)
5.定義和使用新的嵌套類型
6.讓一個已存在的類型遵循一個協(xié)議

  • Extension Syntax

Extensions使用方法:

extension SomeType {
    // new functionality to add to SomeType goes here
}

遵循協(xié)議:

extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol requirements goes here
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末飒炎,一起剝皮案震驚了整個濱河市埋哟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌郎汪,老刑警劉巖赤赊,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怒竿,居然都是意外死亡砍鸠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門耕驰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爷辱,“玉大人,你說我怎么就攤上這事朦肘》构” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵媒抠,是天一觀的道長弟断。 經(jīng)常有香客問我,道長趴生,這世上最難降的妖魔是什么阀趴? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮苍匆,結(jié)果婚禮上刘急,老公的妹妹穿的比我還像新娘。我一直安慰自己浸踩,他們只是感情好叔汁,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著检碗,像睡著了一般据块。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上折剃,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天另假,我揣著相機(jī)與錄音,去河邊找鬼怕犁。 笑死边篮,一個胖子當(dāng)著我的面吹牛开睡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播苟耻,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扶檐!你這毒婦竟也來了凶杖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤款筑,失蹤者是張志新(化名)和其女友劉穎智蝠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奈梳,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡杈湾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了攘须。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漆撞。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖于宙,靈堂內(nèi)的尸體忽然破棺而出浮驳,到底是詐尸還是另有隱情,我是刑警寧澤捞魁,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布至会,位于F島的核電站,受9級特大地震影響谱俭,放射性物質(zhì)發(fā)生泄漏奉件。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一昆著、第九天 我趴在偏房一處隱蔽的房頂上張望县貌。 院中可真熱鬧,春花似錦宣吱、人聲如沸窃这。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杭攻。三九已至,卻和暖如春疤坝,著一層夾襖步出監(jiān)牢的瞬間兆解,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工跑揉, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留锅睛,地道東北人埠巨。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像现拒,于是被迫代替她去往敵國和親辣垒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

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