趁著五一放假又看了幾節(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)造器。
-
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
}