Swift官方文檔的詞匯結(jié)構(gòu)中, 有非常多的關(guān)鍵字, 它們被用于聲明中、語(yǔ)句中、表達(dá)式中、類中、模式中, 還有以數(shù)字符號(hào)#開頭的關(guān)鍵字, 以及特定上下文環(huán)境使用的關(guān)鍵字。另外, 在特性中還有一些關(guān)鍵字, 是以@開頭的關(guān)鍵字。
用在聲明中的關(guān)鍵字?? associatedtype、class、deinit、enum、extension、func、import、init、inout、internal、let、operator、private、protocol、public、open、fileprivate、static、struct、subscript、typealias和var。
用在語(yǔ)句中的關(guān)鍵字??? break、case、continue、default、defer、do、else、fallthrough、for、guard、if、in、repeat、return、switch、where和while。
用在表達(dá)式和類型中的關(guān)鍵字??? as、catch、dynamicType、false、is、nil , rethrows、super、self、Self、throw、throws、true和try。
特定上下文中被保留的關(guān)鍵字??? associativity、convenience、dynamic、didSet、final、get、infix、indirect、lazy、left、mutating、none、nonmutating、optional、override、postfix、precedence、prefix、Protocol、required、right、set、Type、unowned、weak和willSet。
起始于數(shù)字標(biāo)記( # )的關(guān)鍵字??? #available、#column、#else、#elseif、#endif、#file、#function、#if、#line、#selector和#sourceLocation。
用在模式中的關(guān)鍵字? _。
以上的關(guān)鍵字被預(yù)留,不能被用作標(biāo)識(shí)符,除非它們像上一節(jié)標(biāo)識(shí)符中描述的那樣使用反引號(hào)( `),? 才能使用保留字作為標(biāo)識(shí)符。有個(gè)例外是, 特定上下文中被保留的關(guān)鍵字在特定上下文語(yǔ)法之外可以被用于標(biāo)識(shí)符。
以下標(biāo)記被當(dāng)作保留符號(hào),不能用于自定義操作符:(、)、{、}、[、]、.、,、:、;、=、@、#、&(作為前綴操作符)、->、`? 、?和!(作為后綴操作符)。
關(guān)鍵字如何使用
class:用來(lái)聲明一個(gè)類
enum:用來(lái)聲明一個(gè)枚舉
init:相對(duì)于類的釋構(gòu)方法的修飾
let:聲明一個(gè)常量. 類似于const
protocol:協(xié)議.也可以叫接口.這個(gè)往往在很多高級(jí)語(yǔ)言中不能多重繼承的情況下使用協(xié)議是一個(gè)比較好的多態(tài)方式。
break:跳出循環(huán).一般在控制流中使用,比如 for . while switch等語(yǔ)句
case:switch的選擇分支.
continue:跳過本次循環(huán),繼續(xù)執(zhí)行后面的循環(huán).
in:范圍或集合操作,多用于遍歷.
static:聲明靜態(tài)變量或者函數(shù)
struct:聲明定義一個(gè)結(jié)構(gòu)體
precedence:運(yùn)算的優(yōu)先級(jí),越高的話優(yōu)先進(jìn)行計(jì)算。swift 中乘法和除法的優(yōu)先級(jí)是 150 ,加法和減法的優(yōu)先級(jí)是 140 ,這里我們定義點(diǎn)積的優(yōu)先級(jí)為 160 ,就是說(shuō)應(yīng)該早于普通的乘除進(jìn)行運(yùn)算。
unowned, unowned(safe), unowned(unsafe):無(wú)宿主引用。
__COLUMN__:列號(hào)? ,__FILE__:路徑??? , __FUNCTION__: 函數(shù)?? , __LINE__: 行號(hào)
deinit:相對(duì)于類的釋構(gòu)方法的修飾。對(duì)于類的構(gòu)造和釋構(gòu)在swift 中需要使用關(guān)鍵詞來(lái)修飾,而很多高級(jí)語(yǔ)言并不需要特別的指定,便C++ 只需要類名與構(gòu)造函數(shù)名相同就可以,不需要額外的關(guān)鍵詞。
where:用于條件判斷,和數(shù)據(jù)庫(kù)查詢時(shí)的where 'id > 10'這樣功能. swift語(yǔ)言的特性.OC中并沒有。當(dāng)switch的條件滿足where 后面的條件時(shí),才執(zhí)行語(yǔ)句。
is & as:is一般用于對(duì)一些變量的類型做判斷.類似于OC中的isKindClass. as 與強(qiáng)制轉(zhuǎn)換含義雷同.
------------------- -------------------
inout:在函數(shù)的入?yún)⒌念愋颓疤砑右粋€(gè)inout關(guān)鍵字可以定義一個(gè)輸入輸出形式參數(shù)。輸入輸出形式參數(shù)有一個(gè)能輸入給函數(shù)的值,函數(shù)能對(duì)其進(jìn)行修改,還能輸出到函數(shù)外邊替換原來(lái)的值。你只能把變量作為輸入輸出形式參數(shù)的實(shí)際參數(shù)。你不能用常量或者字面量作為實(shí)際參數(shù),因?yàn)槌A亢妥置媪坎荒苄薷摹T趯⒆兞孔鳛閷?shí)際參數(shù)傳遞給輸入輸出形式參數(shù)的時(shí)候,直接在它前邊添加一個(gè)和符合 ( &) 來(lái)明確可以被函數(shù)修改。
inout作為函數(shù)聲明時(shí),引用傳值的關(guān)鍵字。但是在調(diào)用的時(shí)候引用的是地址,所以在引用的時(shí)候要加上&,例如:? functest(inouta:Int ,inoutb :Int){? // 函數(shù)內(nèi)相關(guān)操作 }
varnum1 =3
varnum2 =10
test(&num1,&num2)
------------------- -------------------
extension:擴(kuò)展.類似于OC的categories.
?? 1.Swift 中的可以擴(kuò)展以下幾個(gè):
?? 2.添加計(jì)算型屬性和計(jì)算靜態(tài)屬性
?? 3.定義實(shí)例方法和類型方法
?? 4.提供新的構(gòu)造器
?? 5.定義下標(biāo)
?? 6.定義和使用新的嵌套類型
?? 7.使一個(gè)已有類型符合某個(gè)接口
------------------- -------------------
subscript:下標(biāo)索引修飾.可以讓class、struct、以及enum使用下標(biāo)訪問內(nèi)部的值,指定一個(gè)或多個(gè)輸入形式參數(shù)和返回類型,與實(shí)例方法一樣。與實(shí)例方法不同的是,下標(biāo)可以是讀寫也可以是只讀的。這個(gè)行為通過與計(jì)算屬性中相同的getter和setter傳達(dá):
subscript(index: Int) -> Int {
get { // return an appropriate subscript value here }
set(newValue) { // perform a suitable setting action here }
}
newValue的類型和下標(biāo)的返回值一樣。與計(jì)算屬性一樣,你可以選擇不去指定setter的(newValue)形式參數(shù)。setter默認(rèn)提供形式參數(shù)newValue,如果你自己沒有提供的話。
struct TimesTable {
let multiplier: Int subscript(index: Int) -> Int {?? return multiplier * index?? }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")????? // prints "six times three is 18"
------------------- -------------------
typealias:為此類型聲明一個(gè)別名.和 typedef類似。類型別名可以為已經(jīng)存在的類型定義了一個(gè)新的可選名字。用typealias關(guān)鍵字定義類型別名。一旦為類型創(chuàng)建了一個(gè)別名,你就可以在任何使用原始名字的地方使用這個(gè)別名。
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min
typealias Point = (Int,Int)
let origin: Point = (0,0)
關(guān)于typealias還有一種很高效的用法與協(xié)議組合類型相關(guān)。
------------------- -------------------
協(xié)議組合類型
協(xié)議組合類型允許你指定一個(gè)值,該值的類型遵循多個(gè)協(xié)議的要求而不必顯式定義一個(gè)新的命名型的繼承自每個(gè)你想要該類型遵循的協(xié)議的協(xié)議。比如,指定一個(gè)協(xié)議組合類型 Protocol A & Protocol B & Protocol C 實(shí)際上是和定義一個(gè)新的繼承自 Protocol A , Protocol B , Protocol C 的協(xié)議 Protocol D 是完全一樣的,但不需要引入一個(gè)新名字同理,標(biāo)明一個(gè)協(xié)議組合類型 SuperClass & ProtocolA 與聲明一個(gè)新類型 SubClass 繼承自 SuperClass 并遵循 ProtocolA 是一樣的,但不需要引入新名字。
協(xié)議組合列表中的每項(xiàng)元素必須是類名,協(xié)議名或協(xié)議組合類型、協(xié)議、類的類型別名。列表可以最多包含一個(gè)類。
當(dāng)協(xié)議組合類型包含類型別名,就有可能同一個(gè)協(xié)議在定義中出現(xiàn)不止一次——重復(fù)會(huì)被忽略。比如說(shuō),下面的 PQR 定義等價(jià)于 P & Q & R 。
typealias PQ = P & Q
typealias PQR = PQ & Q & R
------------------- -------------------
associatedtype:定義一個(gè)協(xié)議時(shí),有時(shí)在協(xié)議定義里聲明一個(gè)或多個(gè)關(guān)聯(lián)類型是很有用的。關(guān)聯(lián)類型給協(xié)議中用到的類型一個(gè)占位符名稱。直到采納協(xié)議時(shí),才指定用于該關(guān)聯(lián)類型的實(shí)際類型。關(guān)聯(lián)類型通過 associatedtype 關(guān)鍵字指定。
這里是一個(gè)叫做Container 的示例協(xié)議,聲明了一個(gè)叫做 ItemType 的關(guān)聯(lián)類型:
protocol Container {
? ? associatedtype ItemType
? ? mutating func append(_ item: ItemType)
? ? var count: Int { get }
}
Container 協(xié)議定義了兩個(gè)所有容器必須提供的功能:
1.必須能夠通過 append(_:) 方法向容器中添加新元素
2.必須能夠通過一個(gè)返回 Int 值的 count 屬性獲取容器中的元素?cái)?shù)量
任何遵循 Container協(xié)議的類型必須能指定其存儲(chǔ)值的類型。尤其是它必須保證只有正確類型的元素才能添加到容器中。為了實(shí)現(xiàn)這些要求, Container 協(xié)議聲明了一個(gè)叫做 ItemType 的關(guān)聯(lián)類型,寫作 associatedtype ItemType。
struct IntStack: Container {???? // original IntStack implementation
? ? var items = [Int]()???? // conformance to the Container protocol
? ? typealias ItemType = Int
? ? mutating func append(_ item: Int) {?? // append..? ? }
? ? var count: Int { ?? return items.count? ? }
}
IntStack 為了實(shí)現(xiàn) Container 協(xié)議,指定了適用于ItemType 的類型是 Int 類型。 typealias ItemType = Int 把 ItemType 抽象類型轉(zhuǎn)換為了具體的 Int 類型。
如果你從代碼中刪除了 typealias ItemType = Int ,一切都會(huì)正常運(yùn)行,因?yàn)?ItemType 會(huì)由Swift的類型推斷推斷出來(lái)
------------------- -------------------
fallthrough:break可以忽略不寫,滿足條件時(shí)直接跳出循環(huán).fallthrough 語(yǔ)句用于在 switch 語(yǔ)句中轉(zhuǎn)移控制權(quán)。fallthrough 語(yǔ)句會(huì)把控制權(quán)從 switch 語(yǔ)句中的一個(gè) case 轉(zhuǎn)移到下一個(gè) case。這種控制權(quán)轉(zhuǎn)移是無(wú)條件的,即使下一個(gè) case 的模式與 switch 語(yǔ)句的控制表達(dá)式的值不匹配。
fallthrough 語(yǔ)句可出現(xiàn)在 switch 語(yǔ)句中的任意 case中,但不能出現(xiàn)在最后一個(gè) case 中。同時(shí),fallthrough 語(yǔ)句也不能把控制權(quán)轉(zhuǎn)移到使用了值綁定的 case。
switch 1 {
case 1: print("111")
fallthrough
case 2: print("222")
case 3: print("333")
default: print("default")
} // result is // 111 // 222
--------------------- -------------------
precedenceGroup、precedence(depricate from Swift 4.0)、associativity、left、right、none:自定義的中綴( infix )運(yùn)算符也可以指定優(yōu)先級(jí)和結(jié)合性。優(yōu)先級(jí)和結(jié)合性中詳細(xì)闡述了這兩個(gè)特性是如何對(duì)中綴運(yùn)算符的運(yùn)算產(chǎn)生影響的。以下示例定義了一個(gè)名為+ - 的新自定義中綴運(yùn)算符,該運(yùn)算符屬于優(yōu)先級(jí)組AdditionPrecedence:
infix operator +-: AdditionPrecedence
extension SomeNumber {
? ? static func +- (left: SomeNumber, right: SomeNumber) -> Int {
??? return? left.minNum * left.maxNum + right.minNum * right.maxNum
? ? }
}
print(aaa +- aaa)?? // result is 64
中綴的表達(dá)式中的precedenceGroup 是中綴運(yùn)算符優(yōu)先級(jí)分組。優(yōu)先級(jí)組聲明 (A precedence group declaration) 會(huì)向程序的中綴運(yùn)算符引入一個(gè)全新的優(yōu)先級(jí)組運(yùn)算符的優(yōu)先級(jí)指定運(yùn)算符在沒有分組括號(hào)的情況下綁定到其操作數(shù)的緊密程度。
自定義優(yōu)先級(jí)分組:
precedencegroup 優(yōu)先級(jí)組名稱{
? ? higherThan: 較低優(yōu)先級(jí)組的名稱
? ? lowerThan: 較高優(yōu)先級(jí)組的名稱
? ? associativity: 結(jié)合性
? ? assignment: 賦值性
}
較低優(yōu)先級(jí)組和較高優(yōu)先級(jí)組的名稱說(shuō)明了新建的優(yōu)先級(jí)組是依賴于現(xiàn)存的優(yōu)先級(jí)組的。 lowerThan 優(yōu)先級(jí)組的屬性只可以引用當(dāng)前模塊外的優(yōu)先級(jí)組。當(dāng)兩個(gè)運(yùn)算符為同一個(gè)操作數(shù)競(jìng)爭(zhēng)時(shí),比如表達(dá)式2 + 3 * 5,優(yōu)先級(jí)更高的運(yùn)算符將優(yōu)先參與運(yùn)算。
注意:使用較低和較高優(yōu)先級(jí)組相互聯(lián)系的優(yōu)先級(jí)組必須保持單一層次關(guān)系,但它們不必是線性關(guān)系。這意味著優(yōu)先級(jí)組也許會(huì)有未定義的相關(guān)優(yōu)先級(jí)。這些優(yōu)先級(jí)組的運(yùn)算符在沒有用圓括號(hào)分組的情況下是不能緊鄰著使用的。
Swift定義了許多優(yōu)先組與標(biāo)準(zhǔn)庫(kù)提供的運(yùn)算符一起使用。例如,加(+)和減( - )運(yùn)算符屬于AdditionPrecedence組,乘(*)和除(/)運(yùn)算符屬于MultiplicationPrecedence組。
運(yùn)算符的結(jié)合性(associativity)表示在沒有圓括號(hào)分組的情況下,同樣優(yōu)先級(jí)的一系列運(yùn)算符是如何被分組的。你可以指定運(yùn)算符的結(jié)合性通過上下文關(guān)鍵字left、right或者none,如果沒有指定結(jié)合性,默認(rèn)是none關(guān)鍵字。左關(guān)聯(lián)性的運(yùn)算符是從左至右分組的,例如,相減操作符(-)是左關(guān)聯(lián)性的,所以表達(dá)式4 - 5 - 6被分組為(4 - 5) - 6,得出結(jié)果-7。右關(guān)聯(lián)性的運(yùn)算符是從右往左分組的,指定為none結(jié)合性的運(yùn)算符就沒有結(jié)合性。同樣優(yōu)先級(jí)沒有結(jié)合性的運(yùn)算符不能相鄰出現(xiàn),例如<運(yùn)算符是none結(jié)合性,那表示1 < 2 < 3就不是一個(gè)有效表達(dá)式。
優(yōu)先級(jí)組的賦值性表示在包含可選鏈操作時(shí)的運(yùn)算符優(yōu)先級(jí)。當(dāng)設(shè)為true時(shí),與優(yōu)先級(jí)組對(duì)應(yīng)的運(yùn)算符在可選鏈操作中使用和標(biāo)準(zhǔn)庫(kù)中賦值運(yùn)算符同樣的分組規(guī)則,當(dāng)設(shè)為false或者不設(shè)置,該優(yōu)先級(jí)組的運(yùn)算符與不賦值的運(yùn)算符遵循同樣的可選鏈規(guī)則。
------------------- -------------------
willSet 和 didSet:作用是對(duì)賦值過程前后附加額外的操作。看做是捕獲狀態(tài)然后做操作,在將要賦值的時(shí)候和已經(jīng)賦值的時(shí)候做相關(guān)操作。可以在聲明存儲(chǔ)型變量或?qū)傩詴r(shí)提供willSet和didSet觀察器。一個(gè)包含觀察器的存儲(chǔ)型變量或?qū)傩砸匀缦滦问铰暶鳎?br>var 變量名稱: 類型 = 表達(dá)式{
? ? willSet(setter 名稱) {?? ? ? 語(yǔ)句
? ? }didSet(setter 名稱){??? ? ? 語(yǔ)句
?? }
}
可以在全局范圍、函數(shù)內(nèi)部,或者類、結(jié)構(gòu)的聲明中使用這種形式的聲明。當(dāng)變量以這種形式在全局范圍或者函數(shù)內(nèi)部被聲明時(shí),觀察器表示一個(gè)存儲(chǔ)型變量觀察器。當(dāng)它在類和結(jié)構(gòu)的聲明中被聲明時(shí),觀察器表示一個(gè)屬性觀察器。
可以為任何存儲(chǔ)型屬性添加觀察器。也可以通過重寫父類屬性的方式為任何繼承的屬性(無(wú)論是存儲(chǔ)型還是計(jì)算型的)添加觀察器。
當(dāng)變量或?qū)傩缘闹当桓淖儠r(shí),willSet 和 didSet 觀察器提供了一種觀察方法。觀察器會(huì)在變量的值被改變時(shí)調(diào)用,但不會(huì)在初始化時(shí)被調(diào)用。
willSet 觀察器只在變量或?qū)傩缘闹当桓淖冎罢{(diào)用。新的值作為一個(gè)常量傳入 willSet 觀察器,因此不可以在 willSet 中改變它。didSet 觀察器在變量或?qū)傩缘闹当桓淖兒罅⒓凑{(diào)用。和 willSet 觀察器相反,為了方便獲取舊值,舊值會(huì)傳入 didSet 觀察器。這意味著,如果在變量或?qū)傩缘?didiset 觀察器中設(shè)置值,設(shè)置的新值會(huì)取代剛剛在 willSet 觀察器中傳入的那個(gè)值。
在 willSet 和 didSet 中,圓括號(hào)以及其中的 setter 名稱是可選的。如果提供了一個(gè) setter 名稱,它就會(huì)作為 willSet 和 didSet 的參數(shù)被使用。如果不提供 setter 名稱,willSet 觀察器的默認(rèn)參數(shù)名為 newValue,didSet 觀察器的默認(rèn)參數(shù)名為 oldValue。
提供了 willSet 時(shí),didSet 是可選的。同樣的,提供了 didSet 時(shí),willSet 則是可選的。
------------------- -------------------
mutating、nonmutating:作用:寫在func前面,以便于讓func可以修改struct和protocol的extension中的成員的值。 如果func前面不加mutating,struct和protocol的extension中的成員的值便被保護(hù)起來(lái),不能修改。
結(jié)構(gòu)體和枚舉是值類型。默認(rèn)情況下,值類型屬性不能被自身的實(shí)例方法修改。但是,如果你確實(shí)需要在某個(gè)特定的方法中修改結(jié)構(gòu)體或者枚舉的屬性,你可以為這個(gè)方法選擇可變(mutating)行為,然后就可以從其方法內(nèi)部改變它的屬性;并且這個(gè)方法做的任何改變都會(huì)在方法執(zhí)行結(jié)束時(shí)寫回到原始結(jié)構(gòu)中。方法還可以給它隱含的self屬性賦予一個(gè)全新的實(shí)例,這個(gè)新實(shí)例在方法結(jié)束時(shí)會(huì)替換現(xiàn)存實(shí)例。
結(jié)構(gòu)體中用法:
struct Point {
? ? var x = 0.0, y = 0.0
?? mutating func moveBy(x deltaX: Double, y deltaY: Double) {
? ? ? ? self = Point(x: x + deltaX, y: y + deltaY)
? ? }
}
枚舉中用法:? enum TriStateSwitch {
?? case off, low, high
? ? mutating func next() {
? ? ? ? switch self {
? ? ? ? case .off:
? ? ? ? ? ? self = .low
? ? ? ? case .low:
? ? ? ? ? ? self = .high
? ? ? ? case .high:
? ? ? ? ? ? self = .off
? ? ? ? }
? ? }
}
var ovenLight = TriStateSwitch.low
ovenLight.next()???? // ovenLight is now equal to .high
ovenLight.next()?????? // ovenLight is now equal to .off
在協(xié)議中如何使用? 若你定義了一個(gè)協(xié)議的實(shí)例方法需求,想要改變?nèi)魏尾捎昧嗽搮f(xié)議的類型實(shí)例,只需在協(xié)議里方法的定義當(dāng)中使用 mutating 關(guān)鍵字。這允許結(jié)構(gòu)體和枚舉類型能采用相應(yīng)協(xié)議并滿足方法要求。
protocol Togglable {? ? mutating func toggle()?? }
在Togglable協(xié)議的定義中, toggle() 方法使用 mutating 關(guān)鍵字標(biāo)記,來(lái)表明該方法在調(diào)用時(shí)會(huì)改變遵循該協(xié)議的實(shí)例的狀態(tài):
struct Test: Togglable {
? ? var time: Int = 0
? ? mutating func toggle() {
? ? ? ? self.time = 33333
? ? }
}
var test = Test()
test.time = 2
test.toggle()?? // result is 2
如果你在協(xié)議中標(biāo)記實(shí)例方法需求為 mutating ,在為類實(shí)現(xiàn)該方法的時(shí)候不需要寫 mutating 關(guān)鍵字。 mutating 關(guān)鍵字只在結(jié)構(gòu)體和枚舉類型中需要書寫
--------------------- ---------------------
open、public、internal、fileprivate、private
這些關(guān)鍵字是 Swift 為代碼的實(shí)體提供個(gè)五個(gè)不同的訪問級(jí)別。這些訪問級(jí)別和定義實(shí)體的源文件相關(guān),并且也和源文件所屬的模塊相關(guān)。open 訪問是最高的(限制最少)訪問級(jí)別,private 是最低的(限制最多)訪問級(jí)別。
private“private 訪問, 將實(shí)體的使用限制于封閉聲明中。當(dāng)一些細(xì)節(jié)僅在單獨(dú)的聲明中使用時(shí),使用 private 訪問隱藏特定功能的實(shí)現(xiàn)細(xì)節(jié)。
fileprivate:File-private 訪問, 將實(shí)體的使用限制于當(dāng)前定義源文件中。當(dāng)一些細(xì)節(jié)在整個(gè)文件中使用時(shí),使用 file-private 訪問隱藏特定功能的實(shí)現(xiàn)細(xì)節(jié)。
internal:Internal 訪問, 為默認(rèn)訪問級(jí)別, 允許實(shí)體被定義模塊中的任意源文件訪問,但不能被該模塊之外的任何源文件訪問。通常在定義應(yīng)用程序或是框架的內(nèi)部結(jié)構(gòu)時(shí)使用。
public、open訪問:允許實(shí)體被定義模塊中的任意源文件訪問,同樣可以被另一模塊的源文件通過導(dǎo)入該定義模塊來(lái)訪問。在指定框架的公共接口時(shí),通常使用 open 或 public 訪問。
public 訪問只能在當(dāng)前模塊中被繼承和子類重寫。
open 訪問僅適用于類和類成員,可以在其他模塊外被繼承和子類重寫。
顯式地標(biāo)記類為 open 意味著你考慮過其他模塊使用該類作為父類對(duì)代碼的影響,并且相應(yīng)地設(shè)計(jì)了類的代碼。
訪問控制的注意事項(xiàng)
Swift 中的訪問級(jí)別遵循一個(gè)總體指導(dǎo)準(zhǔn)則:實(shí)體不可以被更低(限制更多)訪問級(jí)別的實(shí)體定義。
比如: 一個(gè) public 的變量其類型的訪問級(jí)別不能是 internal, file-private 或是 private,因?yàn)樵谑褂?public 變量的地方可能沒有這些類型的訪問權(quán)限。
又比如: 函數(shù)類型的訪問級(jí)別由函數(shù)成員類型和返回類型中的最嚴(yán)格訪問級(jí)別決定。一個(gè)函數(shù)不能比它的參數(shù)類型和返回類型訪問級(jí)別高,因?yàn)楹瘮?shù)可以使用的環(huán)境而其參數(shù)和返回類型卻不能使用。
---------------------
final:該修飾符用于修飾類或類中的屬性、方法以及下標(biāo)。如果用它修飾一個(gè)類,那么這個(gè)類不能被繼承。如果用final 修飾類中的屬性、方法或下標(biāo),那么它們不能在子類中被重寫。
使用final的情況, 是類或方法屬性等不希望被繼承和重寫,具體情況一般是:
?? 1.類或者方法的功能確實(shí)已經(jīng)完備了, 基本不會(huì)再繼承和重寫。
?? 2.避免子類繼承和修改造成危險(xiǎn)。有些方法如果被子類繼承重寫會(huì)造成破壞性的后果,導(dǎo)致無(wú)法正常工作,則需要將其標(biāo)為final加以保護(hù)。
?? 3.保證父類的方法一定被執(zhí)行, 我們可以把父類的方法定義成final,同時(shí)將內(nèi)部可以繼承的部分剝離出來(lái),供子類繼承重寫。
還有一中說(shuō)法, 認(rèn)為final能改成性能,因?yàn)榫幾g器能從final中獲取額外的信息,所以可以對(duì)類或者方法調(diào)用進(jìn)行優(yōu)化處理。其實(shí)這樣優(yōu)化對(duì)性能的提升非常有限,所以如果是為了提升性能, 把所有的屬性方法都加上final關(guān)鍵字,也沒有多大的作用。
required:必要構(gòu)造器標(biāo)識(shí)符, 修飾符用于修飾類的指定構(gòu)造器或便利構(gòu)造器,表示該類所有的子類都必須實(shí)現(xiàn)該構(gòu)造器。在子類實(shí)現(xiàn)該構(gòu)造器時(shí),必須同樣使用 required 修飾符修飾該構(gòu)造器。
為了要求子類去實(shí)現(xiàn)超類的構(gòu)造器,使用 required 聲明修飾符標(biāo)記超類的構(gòu)造器。子類實(shí)現(xiàn)超類構(gòu)造器時(shí)也必須使用 required 聲明修飾符。
class SomeClass1 {
? ? required init() {? ? // 構(gòu)造器的實(shí)現(xiàn)代碼? ? }
}
在子類重寫父類的必要構(gòu)造器時(shí),必須在子類的構(gòu)造器前也添加required修飾符,表明該構(gòu)造器要求也應(yīng)用于繼承鏈后面的子類。在重寫父類中必要的指定構(gòu)造器時(shí),不需要添加override修飾符:
class SomeSubclass: SomeClass1 {
? ? required init() {? ? ? ? // 構(gòu)造器的實(shí)現(xiàn)代碼? ? }
}
如果子類繼承的構(gòu)造器能滿足必要構(gòu)造器的要求,則無(wú)須在子類中顯式提供必要構(gòu)造器的實(shí)現(xiàn)。就像下面的代碼, 因?yàn)樽宇惱^承的構(gòu)造器能滿足必要構(gòu)造器的要求, 所以子類的必要構(gòu)造器可以是隱性的。代碼如下:
class SomeClass1 {
? ? required init() {? ?? // 構(gòu)造器的實(shí)現(xiàn)代碼? ? }
}
class SomeSubclass: SomeClass1 {
}
你可以在遵循協(xié)議的類中實(shí)現(xiàn)構(gòu)造器,無(wú)論是作為指定構(gòu)造器,還是作為便利構(gòu)造器。無(wú)論哪種情況,你都必須為構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:
class SomeClass: SomeProtocol {
? ? required init(someParameter: Int) {? ?? // 這里是構(gòu)造器的實(shí)現(xiàn)部分? ? }
}
使用 required 修飾符可以確保所有子類也必須提供此構(gòu)造器實(shí)現(xiàn),從而也能符合協(xié)議。如果類已經(jīng)被標(biāo)記為 final,那么不需要在協(xié)議構(gòu)造器的實(shí)現(xiàn)中使用 required 修飾符,因?yàn)?final 類不能有子類。如果這個(gè)類還沒有用 final 聲明修飾符標(biāo)記,這個(gè)構(gòu)造器必須用 required 聲明修飾符標(biāo)記。
這就是為什么在日常開發(fā)中, 當(dāng)我們繼承系統(tǒng)某各類去指定一個(gè)新的構(gòu)造器時(shí), 系統(tǒng)總是編譯報(bào)錯(cuò), 提示添加如下代碼:
required init?(coder aDecoder: NSCoder) {
? ? ? ? fatalError("init(coder:) has not been implemented")
? ? }
這種情況一般會(huì)出現(xiàn)在繼承了遵守NSCoding protocol的類,比如UIView系列的類、UIViewController系列的類。這是NSCoding protocol定義的,遵守了NSCoding protoaol的所有類必須繼承。當(dāng)我們?cè)谧宇惗x了指定初始化器(包括自定義和重寫父類指定初始化器),那么必須顯示實(shí)現(xiàn)required init?(coder aDecoder: NSCoder),而其他情況下則會(huì)隱式繼承。
如果一個(gè)子類重寫了父類的指定構(gòu)造器,并且該構(gòu)造器滿足了某個(gè)協(xié)議的要求,那么該構(gòu)造器的實(shí)現(xiàn)需要同時(shí)標(biāo)注 required 和 override 修飾符:
protocol SomeProtocol {
? ? init()
}
class SomeSuperClass {
? ? init() {? ? ? // 這里是構(gòu)造器的實(shí)現(xiàn)部分? ? }
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
?? // 因?yàn)樽裱瓍f(xié)議,需要加上 required
? ? // 因?yàn)槔^承自父類,需要加上 override
? ? required override init() {? ? ? ? // 這里是構(gòu)造器的實(shí)現(xiàn)部分? ? }
}
------------------- -------------------
class var:在swift中對(duì)于enum和struct來(lái)說(shuō)支持用static關(guān)鍵字來(lái)標(biāo)示靜態(tài)變量,但是對(duì)于class成員來(lái)說(shuō),只能以class var的方式返回一個(gè)只讀值。例如:
struct SomeStructure {
staticvarstoredTypeProperty ="Some value."
staticvarcomputedTypeProperty:Int{?? // return an Int value here? }
}
enum SomeEnumeration {
staticvarstoredTypeProperty ="Some value."
staticvarcomputedTypeProperty:Int{???? // return an Int value here? }
}
class SomeClass {
class var computedTypeProperty: Int { }
}
這樣其實(shí)很好的區(qū)分了struct和class的功能,不像C# 抓來(lái)一個(gè)隨便用,但相對(duì)于oc來(lái)講其實(shí)是弱化了界限,
如果你想在class中搞一個(gè)非只讀的靜態(tài)變量出來(lái),可以和struct進(jìn)行配合。
------------------- --------------------
convenience:用來(lái)進(jìn)行方便的初始化,就相當(dāng)于構(gòu)造函數(shù)重載。便利構(gòu)造器是類中比較次要的、輔助型的構(gòu)造器。你可以定義便利構(gòu)造器來(lái)調(diào)用同一個(gè)類中的指定構(gòu)造器,并為其參數(shù)提供默認(rèn)值。你也可以定義便利構(gòu)造器來(lái)創(chuàng)建一個(gè)特殊用途或特定輸入值的實(shí)例。
如果你的類不需要便利構(gòu)造器你可以不提供它。在為通用的初始化模式創(chuàng)建快捷方式以節(jié)省時(shí)間或者類的初始化更加清晰明了的時(shí)候時(shí)候便利構(gòu)造器。
便利構(gòu)造器有著相同的書寫方式,但是要用 convenience 修飾符放到 init 關(guān)鍵字前,用空格隔開:
convenience init(parameters) {?? statements? }
class Food {
? ? var name: String
? ? init(name: String) {
? ? ? ? self.name = name
? ? }
? ? convenience init() {? ? ? self.init(name: "[Unnamed]")? ? }
}
var food = Food.init()
print(food.name)????????? // result is [Unnamed]
便利構(gòu)造器可以將構(gòu)造過程委托給另一個(gè)便利構(gòu)造器或一個(gè)指定構(gòu)造器。但是,類的構(gòu)造過程必須以一個(gè)將類中所有屬性完全初始化的指定構(gòu)造器的調(diào)用作為結(jié)束。便利構(gòu)造器不能調(diào)用超類的構(gòu)造器。
對(duì)于class來(lái)講,默認(rèn)或指定的初始化方法作為所謂的Designated初始化。
若重載的初始化需要調(diào)用Designated初始化則將它作為convenience初始化,在方法前要加上convenience關(guān)鍵字。
class Figure{
varname:String!
varnikname:String?
init(){?? name ="John"? ? ? }
convenienceinit(name:String!,nikname:String!) {
self.init()self.name = nameself.nikname = nikname
? ? ? }
? ? }
------------------- --------------------
dynamic:Swift 中的函數(shù)可以是靜態(tài)調(diào)用,靜態(tài)調(diào)用會(huì)更快。Swift的代碼直接被編譯優(yōu)化成靜態(tài)調(diào)用的時(shí)候,就不能從Objective-C 中的SEL字符串來(lái)查找到對(duì)應(yīng)的IMP了。這樣就需要在 Swift 中添加一個(gè)關(guān)鍵字 dynamic,告訴編譯器這個(gè)方法是可能被動(dòng)態(tài)調(diào)用的,需要將其添加到查找表中。
純Swift類沒有動(dòng)態(tài)性,但在方法、屬性前添加dynamic修飾可以獲得動(dòng)態(tài)性。該修飾符用于修飾任何兼容 Objective-C 的類的成員。訪問被 dynamic 修飾符標(biāo)記的類成員將總是由 Objective-C 運(yùn)行時(shí)系統(tǒng)進(jìn)行動(dòng)態(tài)派發(fā),而不會(huì)由編譯器進(jìn)行內(nèi)聯(lián)或消虛擬化。
繼承自NSObject的Swift類,其繼承自父類的方法具有動(dòng)態(tài)性,其他自定義方法、屬性需要加dynamic修飾才可以獲得動(dòng)態(tài)性。而且因?yàn)槭褂脛?dòng)態(tài)修飾符標(biāo)記的聲明是使用Objective-C運(yùn)行時(shí)分派的,所以它們必須用objc屬性標(biāo)記。(從Swift 4.0開始, 加dynamic 修飾符時(shí)必須是顯式的objc了)
純Swift類中的dynamic的使用:
class DynamicSwiftClass {
? ? var zero = 0
? ? @objc dynamic var fist = 1
? ? @objc func dynamicFunc() {
? ? }
//? ? open this code will be error
//? ? @objc dynamic var adddd = (0 , 0)
//? ? @objc dynamic func someMethod(value: Int) -> (Int, Int) {
//? ? ? ? return (1, 1)
//? ? }
}
若方法的參數(shù)、屬性類型為Swift特有、無(wú)法映射到Objective-C的類型(如Character、Tuple),則此方法、屬性無(wú)法添加dynamic修飾, 一旦添加就會(huì)編譯報(bào)錯(cuò)。
--------------------- ---------------------
operator、prefix、postfix、infix:除了實(shí)現(xiàn)標(biāo)準(zhǔn)運(yùn)算符,在 Swift 當(dāng)中還可以聲明和實(shí)現(xiàn)自定義運(yùn)算符(custom operators)。可以用來(lái)自定義運(yùn)算符的字符列表請(qǐng)參考運(yùn)算符。新的運(yùn)算符要在全局作用域內(nèi),使用 operator 關(guān)鍵字進(jìn)行聲明,同時(shí)還要指定 prefix 、infix 或者 postfix 限定符, 語(yǔ)法結(jié)構(gòu)如下:
prefix operator `operatorName`
postfix operator `operatorName`
infix operator operatorname: `precedenceGroup`
上面的代碼定義了一個(gè)新的名為 +++ 的前綴運(yùn)算符。這個(gè)運(yùn)算符在 Swift 中并沒有意義,我們針對(duì)下面這個(gè)類SomeNumer的實(shí)例來(lái)賦予它意義。對(duì)這個(gè)例子來(lái)講, +++ 作為“平方”運(yùn)算符。
prefix operator +++
class SomeNumber {
? ? var minNum = 0
? ? var maxNum = 0
? ? static prefix func +++(number: SomeNumber) -> SomeNumber {
? ? ? ? number.minNum = number.minNum * number.minNum
? ? ? ? number.maxNum = number.maxNum * number.maxNum
? ? ? ? return number
? ? }
}
var aaa = SomeNumber()
aaa.minNum = 3
aaa.maxNum = 6
+++aaa
print(aaa.minNum, aaa.maxNum)??? // result is "9 36\n"
需要注意的地方是, 當(dāng)使用自定義運(yùn)算時(shí), 傳入的參數(shù)至少要有一個(gè)當(dāng)前對(duì)象, 否則編譯不會(huì)通過。定義前綴或后綴運(yùn)算符時(shí),不要指定優(yōu)先級(jí)。但是,如果將前綴和后綴運(yùn)算符應(yīng)用于相同的操作時(shí),則首先進(jìn)行后綴運(yùn)算。上面這個(gè)例子是前綴prefix, 當(dāng)然后綴 postfix也是同樣的用法, 還有一個(gè)中綴 infix是比較特殊的, 涉及到結(jié)合性associativity 和 優(yōu)先級(jí)precedence的使用。下面繼續(xù)來(lái)進(jìn)行說(shuō)明。
------------------- --------------------
defer:defer{?? statement? }? 用來(lái)包裹一段代碼,這個(gè)代碼塊將會(huì)在當(dāng)前作用域結(jié)束的時(shí)候被調(diào)用。這通常被用來(lái)對(duì)當(dāng)前的代碼進(jìn)行一些清理工作,比如關(guān)閉打開的文件等。可以在同一個(gè)作用域中指定多個(gè) defer 代碼塊,在當(dāng)前作用域結(jié)束時(shí),它們會(huì)以相反的順序被調(diào)用,即先定義的后執(zhí)行,后定義的先執(zhí)行。
在 defer 語(yǔ)句中的語(yǔ)句無(wú)論程序控制如何轉(zhuǎn)移都會(huì)被執(zhí)行。在某些情況下,例如,手動(dòng)管理資源時(shí),比如關(guān)閉文件描述符,或者即使拋出了錯(cuò)誤也需要執(zhí)行一些操作時(shí),就可以使用 defer 語(yǔ)句。
如果多個(gè) defer 語(yǔ)句出現(xiàn)在同一作用域內(nèi),那么它們執(zhí)行的順序與出現(xiàn)的順序相反。給定作用域中的第一個(gè) defer 語(yǔ)句,會(huì)在最后執(zhí)行,這意味著代碼中最靠后的 defer 語(yǔ)句中引用的資源可以被其他 defer 語(yǔ)句清理掉。
func f() {
? ? defer { print("First") }
? ? defer { print("Second") }
? ? defer { print("Third") }
}
f()?? // 打印 “Third”???? // 打印 “Second”??? // 打印 “First”
defer 語(yǔ)句中的語(yǔ)句無(wú)法將控制權(quán)轉(zhuǎn)移到 defer 語(yǔ)句外部。
------------------- --------------------
guard:當(dāng)某些條件不滿足的情況下,跳出作用域.
unc testFunc(input:Int){
guardinput <10else{
print("Input must < 10")
return
? ? ? ? ? }
print("Input is \\(input)")}
testFunc(1)
testFunc(11)
與if用法一樣,但是作用與if相反.相比if來(lái)說(shuō),guard有一個(gè)好處:如果不使用return,break,continue,throw跳出當(dāng)前作用域,編譯器會(huì)報(bào)錯(cuò).所以,對(duì)那些對(duì)條件要求十分嚴(yán)格的地方,guard是不二之選。guard也可以使用可選綁定(Optional Binding)也就是guard? let的格式
func testMathFunc(input:Int?){
guardlet_= inputelse{
print("Input cannot be nil")
return
? ? ? }
}
testMathFunc(nil)
----------------------------------------
optional:該修飾符用于修飾協(xié)議中的屬性、方法以及下標(biāo)成員,表示符合類型可以不實(shí)現(xiàn)這些成員要求。
可選類型:Swift 為命名類型 Optional<Wrapped> 定義后綴 ? 作為語(yǔ)法糖 ,其定義在 Swift 標(biāo)準(zhǔn)庫(kù)中。換句話說(shuō),下列兩種聲明是等價(jià)的:
var optionalInteger: Int?
var optionalInteger: Optional<Int>
在上述兩種情況下,變量 optionalInteger 都聲明為可選整數(shù)類型。注意在類型和 ? 之間沒有空格。
類型 Optional<Wrapped> 是有兩種情況的, none 和 Some(Wrapped) ,它代表可能沒有值或可能有值。任何類型都可以被顯式的聲明(或隱式的轉(zhuǎn)換)為可選類型。如果你在聲明可選的變量或?qū)傩詴r(shí)沒有提供初始值,它的值則會(huì)默認(rèn)為 nil 。
使用 ! 操作符獲解析一個(gè)值為 nil 的可選項(xiàng)會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。你也可以使用可選鏈和可選綁定來(lái)有條件地執(zhí)行對(duì)可選表達(dá)式的操作。如果值為 nil ,不會(huì)執(zhí)行任何操作并且不會(huì)因此產(chǎn)生運(yùn)行時(shí)錯(cuò)誤。
隱式展開可選類型:Swift 為命名類型 Optional<Wrapped> 定義后綴 ! 作為語(yǔ)法糖 ,其定義在 Swift 標(biāo)準(zhǔn)庫(kù)中,作為它被訪問時(shí)自動(dòng)解析的附加行為。如果你試圖使用一個(gè)值為 nil 的隱式解析,你會(huì)得到一個(gè)運(yùn)行時(shí)錯(cuò)誤。除了隱式展開的行為之外,下面兩個(gè)聲明是等價(jià)的:
var implicitlyUnwrappedString: String!
var explicitlyUnwrappedString: Optional<String>
注意類型與 ! 之間沒有空格。
有了可選項(xiàng),如果在聲明隱式展開可選變量或?qū)傩詴r(shí)你不用提供初始值,它的值會(huì)默認(rèn)為 nil 。使用可選鏈有條件地對(duì)隱式展開可選項(xiàng)的表達(dá)式進(jìn)行操作。如果值為 nil ,就不執(zhí)行任何操作,因此也不會(huì)產(chǎn)生運(yùn)行錯(cuò)誤。
可選的協(xié)議:協(xié)議可以定義可選要求,遵循協(xié)議的類型可以選擇是否實(shí)現(xiàn)這些要求。在協(xié)議中使用 optional 關(guān)鍵字作為前綴來(lái)定義可選要求。可選要求用在你需要和 Objective-C 打交道的代碼中。協(xié)議和可選要求都必須帶上objc屬性。標(biāo)記 objc 特性的協(xié)議只能被繼承自 Objective-C 類的類或者 objc 類遵循,其他類以及結(jié)構(gòu)體和枚舉均不能遵循這種協(xié)議。只能將 optional 修飾符用于被 objc 特性標(biāo)記的協(xié)議。這樣一來(lái),就只有類類型可以采納并符合擁有可選成員要求的協(xié)議。
使用可選要求時(shí)(例如,可選的方法或者屬性),它們的類型會(huì)自動(dòng)變成可選的。比如,一個(gè)類型為 (Int) -> String 的方法會(huì)變成((Int) -> String)?。需要注意的是整個(gè)函數(shù)類型是可選的,而不是函數(shù)的返回值。
協(xié)議中的可選要求可通過可選鏈?zhǔn)秸{(diào)用來(lái)使用,因?yàn)樽裱瓍f(xié)議的類型可能沒有實(shí)現(xiàn)這些可選要求。類似 someOptionalMethod?(someArgument) 這樣,你可以在可選方法名稱后加上 ? 來(lái)調(diào)用可選方法。
@objc protocol CounterDataSource {
@objc optional var fixedIncrement: Int { get }
@objc optional func incrementForCount() -> Int
}
class Counter {
? ? var count = 0
? ? var dataSource: CounterDataSource?
? ? func increment() {
? ? ? ? if let amount = dataSource?.incrementForCount?() {
? ? ? ? ? ? count += amount
? ? ? ? } else if let amount = dataSource?.fixedIncrement {
? ? ? ? ? ? count += amount
? ? ? ? }
? ? }
}
class ThreeSource: NSObject, CounterDataSource {
? ? let fixedIncrement = 3
}
var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
? ? counter.increment()
? ? print(counter.count)
}
當(dāng)沒有代理沒有實(shí)現(xiàn)可選的協(xié)議時(shí), dataSource?.incrementForCount?()為nil, 只有當(dāng)代理實(shí)現(xiàn)了此協(xié)議方法時(shí), amount才會(huì)是返回的那個(gè)值。
--------------------- ---------------------
indirect:遞歸枚舉是一種枚舉類型,它有一個(gè)或多個(gè)枚舉成員使用該枚舉類型的實(shí)例作為關(guān)聯(lián)值。使用遞歸枚舉時(shí),編譯器會(huì)插入一個(gè)間接層。你可以在枚舉成員前加上indirect來(lái)表示該成員可遞歸, 而且被 indirect 修飾符標(biāo)記的枚舉用例必須有一個(gè)關(guān)聯(lián)值。。
enum ArithmeticExpression {
? ? case number(Int)
? ? indirect case addition(ArithmeticExpression, ArithmeticExpression)
? ? indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
你也可以在枚舉類型開頭加上indirect關(guān)鍵字來(lái)表明它的所有成員都是可遞歸的:
indirect enum ArithmeticExpression {
? ? case number(Int)
? ? case addition(ArithmeticExpression, ArithmeticExpression)
? ? case multiplication(ArithmeticExpression, ArithmeticExpression)
}
上面定義的枚舉類型可以存儲(chǔ)三種算術(shù)表達(dá)式:純數(shù)字、兩個(gè)表達(dá)式相加、兩個(gè)表達(dá)式相乘。枚舉成員addition和multiplication的關(guān)聯(lián)值也是算術(shù)表達(dá)式。
下面的代碼展示了使用ArithmeticExpression這個(gè)遞歸枚舉創(chuàng)建表達(dá)式(5 + 4) * 2:
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)
使用這個(gè)枚舉:
func evaluate(_ expression: ArithmeticExpression) -> Int {
? ? switch expression {
? ? case let .number(value):
? ? ? ? return value
? ? case let .addition(left, right):
? ? ? ? return evaluate(left) + evaluate(right)
? ? case let .multiplication(left, right):
? ? ? ? return evaluate(left) * evaluate(right)
? ? }
}
print(evaluate(product))??? // 打印 "18"
------------------------------------------
do 、 try 、 catch 、throw 、 throws、rethrows:表示錯(cuò)誤。這些關(guān)鍵字都是關(guān)于錯(cuò)誤處理的, 錯(cuò)誤處理是相應(yīng)和接收來(lái)自你程序中錯(cuò)誤條件的過程。Swift 給運(yùn)行時(shí)可恢復(fù)錯(cuò)誤的拋出、捕獲、傳遞和操縱提供了一類支持。
在 Swift 中,錯(cuò)誤表示為遵循 Error 協(xié)議類型的值。這個(gè)空的協(xié)議明確了一個(gè)類型可以用于錯(cuò)誤處理。
Swift 枚舉是典型的為一組相關(guān)錯(cuò)誤條件建模的完美配適類型,關(guān)聯(lián)值還允許錯(cuò)誤錯(cuò)誤通訊攜帶額外的信息。比如說(shuō),SomeError 的錯(cuò)誤條件:
enum SomeError:Error{
caseSomeError1
caseSomeError2
caseSomeError3(code:Int)
}
拋出一個(gè)錯(cuò)誤允許你明確某些意外的事情發(fā)生了并且正常的執(zhí)行流不能繼續(xù)下去。你可以使用 throw 語(yǔ)句來(lái)拋出一個(gè)錯(cuò)誤。
throw SomeError.SomeError2
throw SomeError.SomeError3(code: value)
拋出錯(cuò)誤:為了明確一個(gè)函數(shù)或者方法可以拋出錯(cuò)誤,你要在它的聲明當(dāng)中的形式參數(shù)后邊寫上 throws關(guān)鍵字。使用 throws標(biāo)記的函數(shù)叫做拋出函數(shù)。如果它明確了一個(gè)返回類型,那么 throws關(guān)鍵字要在返回箭頭 ( ->)之前。
func makeSomeError(value: Int)
func makeSomeError(value: Int) throws
func makeSomeError(value: Int) throws -> String
但是只有拋出函數(shù)可以傳遞錯(cuò)誤。任何在非拋出函數(shù)中拋出的錯(cuò)誤都必須在該函數(shù)內(nèi)部處理。函數(shù)類型如果要拋出錯(cuò)誤就必須使用 throws 關(guān)鍵字標(biāo)記,而且能重拋錯(cuò)誤的函數(shù)類型必須使用 rethrows 關(guān)鍵字標(biāo)記。
完善這個(gè)可拋異常的函數(shù)實(shí)現(xiàn):
func makeSomeError(value: Int) throws {
? ? switch value {
? ? case 1:
? ? ? ? throw SomeError.SomeError1
? ? case 2:
? ? ? ? throw SomeError.SomeError2
? ? case 3:
? ? ? ? throw SomeError.SomeError3(code: 888)
? ? case 4:? // 默認(rèn)的這里隨便找了一個(gè)錯(cuò)誤, 來(lái)說(shuō)明catch的范圍
? ? ? ? throw MachError(.exceptionProtected)
? ? default:
? ? ? ? print("excute normal code")
? ? }
}
處理錯(cuò)誤:在 Swift 中有四種方式來(lái)處理錯(cuò)誤。你可以將來(lái)自函數(shù)的錯(cuò)誤傳遞給調(diào)用函數(shù)的代碼中,使用 do-catch 語(yǔ)句來(lái)處理錯(cuò)誤,把錯(cuò)誤作為可選項(xiàng)的值,或者錯(cuò)誤不會(huì)發(fā)生的斷言。
使用 do-catch語(yǔ)句來(lái)通過運(yùn)行一段代碼處理錯(cuò)誤。如果do分句中拋出了一個(gè)錯(cuò)誤,它就會(huì)與 catch分句匹配,以確定其中之一可以處理錯(cuò)誤。這是 do-catch語(yǔ)句的通常使用語(yǔ)法:
do {
? ? try expression
? ? statements
} catch pattern 1 {
? ? statements
} catch pattern 2 where condition {
? ? statements
}
按照上面的例子來(lái)寫, 如下:
do {
? ? try makeSomeError(value: 1)
} catch SomeError.SomeError1 {
? ? print("SomeError1")
} catch SomeError.SomeError2 {
? ? print("SomeError2")
} catch SomeError.SomeError3(let anyCode) {
? ? print("SomeError3 code is \(anyCode)")
}
結(jié)合三者, 就是一個(gè)完整的例子, 當(dāng)我們執(zhí)行如上代碼時(shí), 將會(huì)catch 到 SomeError1 并打印。
如果將 try 語(yǔ)句換為如下代碼時(shí), 打印結(jié)果如下:
try makeSomeError(value: 3)
// SomeError2
try makeSomeError(value: 3)
// SomeError3 code is 888
try makeSomeError(value: 4)
// nothing print, because can't catch
try makeSomeError(value: 5)
// excute normal code
當(dāng)makeSomeError執(zhí)行 default分支時(shí), 拋出的異常是不能 處理的, 因?yàn)閏atch中沒有涉及相關(guān)的異常所以catch不到的
----------------------------------------
dynamicType:(depricate from Swift 4.0 不建議在4.0使已經(jīng)廢除) 3.0用type(of:)代替。獲取對(duì)象的動(dòng)態(tài)類型,即運(yùn)行時(shí)的實(shí)際類型,而非代碼指定或編譯器看到的類型。
----------------------------------------
注:set、get 、new、self、super、none、if 、for、return文中沒提到的就不一一介紹了。沒提到的都是最基本的或者我不知道的或者不常用的關(guān)鍵字,后面接觸到新的再繼續(xù)記錄.