Swift官方文檔閱讀筆記(函數(shù)、閉包怪蔑、枚舉、類和結(jié)構(gòu)體丧荐、屬性缆瓣、方法、初始化)

Swift中文文檔連接

函數(shù)相關(guān)

可變形式參數(shù)

一個(gè)可變形式參數(shù)可以接受零或者多個(gè)特定類型的值虹统。當(dāng)調(diào)用函數(shù)的時(shí)候你可以利用可變形式參數(shù)來聲明形式參數(shù)可以被傳入值的數(shù)量是可變的弓坞∷砩酰可以通過在形式參數(shù)的類型名稱后邊插入三個(gè)點(diǎn)符號(hào)( ...)來書寫可變形式參數(shù)。

傳入到可變參數(shù)中的值在函數(shù)的主體中被當(dāng)作是對(duì)應(yīng)類型的數(shù)組渡冻。舉個(gè)栗子戚扳,一個(gè)可變參數(shù)的名字是 numbers類型是 Double...在函數(shù)的主體中它會(huì)被當(dāng)作名字是 numbers 類型是 [Double]的常量數(shù)組。

下面的栗子計(jì)算了一組任意長(zhǎng)度的數(shù)字的算術(shù)平均值(也叫做平均數(shù))族吻。

  func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers

注意
一個(gè)函數(shù)最多只能有一個(gè)可變形式參數(shù)帽借。

輸入輸出形式參數(shù)

就像上面描述的,可變形式參數(shù)只能在函數(shù)的內(nèi)部做改變超歌。如果你想函數(shù)能夠修改一個(gè)形式參數(shù)的值砍艾,而且你想這些改變?cè)诤瘮?shù)結(jié)束之后依然生效,那么就需要將形式參數(shù)定義為輸入輸出形式參數(shù)巍举。

在形式參數(shù)定義開始的時(shí)候在前邊添加一個(gè) inout關(guān)鍵字可以定義一個(gè)輸入輸出形式參數(shù)脆荷。輸入輸出形式參數(shù)有一個(gè)能輸入給函數(shù)的值,函數(shù)能對(duì)其進(jìn)行修改懊悯,還能輸出到函數(shù)外邊替換原來的值蜓谋。

你只能把變量作為輸入輸出形式參數(shù)的實(shí)際參數(shù)。你不能用常量或者字面量作為實(shí)際參數(shù)炭分,因?yàn)槌A亢妥置媪坎荒苄薷墓屡臁T趯⒆兞孔鳛閷?shí)際參數(shù)傳遞給輸入輸出形式參數(shù)的時(shí)候,直接在它前邊添加一個(gè)和符號(hào) ( &) 來明確可以被函數(shù)修改欠窒。

注意

輸入輸出形式參數(shù)不能有默認(rèn)值覆旭,可變形式參數(shù)不能標(biāo)記為 inout,如果你給一個(gè)形式參數(shù)標(biāo)記了 inout岖妄,那么它們也不能標(biāo)記 var和 let了型将。

這里有一個(gè) swapTwoInts(::)函數(shù),它有兩個(gè)輸入輸出整數(shù)形式參數(shù) a和 b:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

函數(shù) swapTwoInts(::)只是簡(jiǎn)單的將 b和 a的值進(jìn)行了調(diào)換荐虐。函數(shù)將 a的值儲(chǔ)存在臨時(shí)常量 temporaryA中七兜,將 b的值賦給 a,然后再將 temporaryA的值賦給 b福扬。

你可以通過兩個(gè) Int類型的變量來調(diào)用函數(shù) swapTwoInts(::)去調(diào)換它們兩個(gè)的值腕铸,需要注意的是 someInt的值和 anotherInt的值在傳入函數(shù) swapTwoInts(::)時(shí)都添加了和符號(hào)。

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"

上邊的栗子顯示了 someInt 和 anotherInt的原始值即使是在函數(shù)的外部定義的铛碑,也可被函數(shù) swapTwoInts(::)修改狠裹。

注意

輸入輸出形式參數(shù)與函數(shù)的返回值不同。上邊的 swapTwoInts沒有定義返回類型和返回值汽烦,但它仍然能修改 someInt和 anotherInt的值涛菠。輸入輸出形式參數(shù)是函數(shù)能影響到函數(shù)范圍外的另一種替代方式。


閉包相關(guān)

涉及關(guān)鍵字:尾隨閉包,逃逸閉包 @escaping俗冻,自動(dòng)閉包 @autoclosure 閉包是引用類型
https://www.cnswift.org/closures


枚舉相關(guān)

關(guān)聯(lián)值

有時(shí)將其它類型的關(guān)聯(lián)值與這些成員值一起存儲(chǔ)是很有用的礁叔。這樣你就可以將額外的自定義信息和成員值一起儲(chǔ)存,并且允許你在代碼中使用每次調(diào)用這個(gè)成員時(shí)都能使用它迄薄。
你可以定義 Swift 枚舉來存儲(chǔ)任意給定類型的關(guān)聯(lián)值琅关,如果需要的話不同枚舉成員關(guān)聯(lián)值的類型可以不同。
在Moya里面的使用場(chǎng)景
例如:

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

這可以讀作:
“定義一個(gè)叫做 Barcode的枚舉類型讥蔽,它要么用 (Int, Int, Int, Int)類型的關(guān)聯(lián)值獲取 upc 值涣易,要么用 String 類型的關(guān)聯(lián)值獲取一個(gè) qrCode的值∏诶海”

遞歸枚舉

關(guān)鍵字:indirect

示例:

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

類和結(jié)構(gòu)體

類與結(jié)構(gòu)體的對(duì)比

在 Swift 中類和結(jié)構(gòu)體有很多共同之處都毒,它們都能:

  • 定義屬性用來存儲(chǔ)值;
  • 定義方法用于提供功能碰缔;
  • 定義下標(biāo)腳本用來允許使用下標(biāo)語法訪問值账劲;
  • 定義初始化器用于初始化狀態(tài);
  • 可以被擴(kuò)展來默認(rèn)所沒有的功能金抡;
  • 遵循協(xié)議來針對(duì)特定類型提供標(biāo)準(zhǔn)功能瀑焦。

類有而結(jié)構(gòu)體沒有的額外功能:

  • 繼承允許一個(gè)類繼承另一個(gè)類的特征;
  • 類型轉(zhuǎn)換允許你在運(yùn)行檢查和解釋一個(gè)類實(shí)例的類型;
  • 反初始化器允許一個(gè)類實(shí)例釋放任何其所被分配的資源梗肝;
  • 引用計(jì)數(shù)允許不止一個(gè)對(duì)類實(shí)例的引用榛瓮。

注意

結(jié)構(gòu)體在你的代碼中通過復(fù)制來傳遞,并且并不會(huì)使用引用計(jì)數(shù)巫击。

結(jié)構(gòu)體和枚舉是值類型

值類型是一種當(dāng)它被指定到常量或者變量禀晓,或者被傳遞給函數(shù)時(shí)會(huì)被拷貝的類型。

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
println("cinema is now \(cinema.width) pixels wide")
  //println "cinema is now 2048 pixels wide"
print("hd is still \(hd.width) pixels wide")
// prints "hd is still 1920 pixels wide"

類是引用類型

類和結(jié)構(gòu)體之間的選擇

按照通用準(zhǔn)則坝锰,當(dāng)符合以下一條或多條情形時(shí)應(yīng)考慮創(chuàng)建一個(gè)結(jié)構(gòu)體:

  • 結(jié)構(gòu)體的主要目的是為了封裝一些相關(guān)的簡(jiǎn)單數(shù)據(jù)值粹懒;
  • 當(dāng)你在賦予或者傳遞結(jié)構(gòu)實(shí)例時(shí),有理由需要封裝的數(shù)據(jù)值被拷貝而不是引用顷级;
  • 任何存儲(chǔ)在結(jié)構(gòu)體中的屬性是值類型凫乖,也將被拷貝而不是被引用;
  • 結(jié)構(gòu)體不需要從一個(gè)已存在類型繼承屬性或者行為弓颈。

合適的結(jié)構(gòu)體候選者包括:

  • 幾何形狀的大小帽芽,可能封裝了一個(gè) width屬性和 height屬性,兩者都為 double類型翔冀;
  • 一定范圍的路徑导街,可能封裝了一個(gè) start屬性和 length屬性,兩者為 Int類型橘蜜;
  • 三維坐標(biāo)系的一個(gè)點(diǎn)菊匿,可能封裝了 x , y 和 z屬性付呕,他們都是 double類型计福。

屬性

注意

  • 如果被標(biāo)記為 lazy 修飾符的屬性同時(shí)被多個(gè)線程訪問并且屬性還沒有被初始化跌捆,則無法保證屬性只初始化一次。
  • 全局常量和變量永遠(yuǎn)是延遲計(jì)算的象颖,與延遲存儲(chǔ)屬性有著相同的行為佩厚。不同于延遲存儲(chǔ)屬性,全局常量和變量不需要標(biāo)記 lazy 修飾符说订。

方法

在實(shí)例方法中修改值類型

關(guān)鍵字:mutating

    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// prints "The point is now at (3.0, 4.0)"

//你不能在常量結(jié)構(gòu)體類型里調(diào)用異變方法抄瓦,因?yàn)樽陨韺傩圆荒鼙桓淖儯退闼鼈兪亲兞繉傩裕?let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveBy(x: 2.0, y: 3.0)
// this will report an error

在異變方法里指定自身

異變方法可以指定整個(gè)實(shí)例給隱含的 self屬性陶冷。上文中那個(gè) Point的栗子可以用下邊的代碼代替:

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)
    }
}

初始化

類類型的初始化器委托

為了簡(jiǎn)化指定和便捷初始化器之間的調(diào)用關(guān)系钙姊,Swift 在初始化器之間的委托調(diào)用有下面的三個(gè)規(guī)則:

  • 指定初始化器必須從它的直系父類調(diào)用指定初始化器。

  • 便捷初始化器必須從相同的類里調(diào)用另一個(gè)初始化器埂伦。

  • 便捷初始化器最終必須調(diào)用一個(gè)指定初始化器煞额。

簡(jiǎn)單記憶的這些規(guī)則的方法如下:

  • 指定初始化器必須總是向上委托。
  • 便捷初始化器必須總是橫向委托沾谜。


    initializerDelegation01_2x.png

兩段式初始化

Swift 的類初始化是一個(gè)兩段式過程膊毁。在第一個(gè)階段,每一個(gè)存儲(chǔ)屬性被引入類為分配了一個(gè)初始值基跑。一旦每個(gè)存儲(chǔ)屬性的初始狀態(tài)被確定婚温,第二個(gè)階段就開始了,每個(gè)類都有機(jī)會(huì)在新的實(shí)例準(zhǔn)備使用之前來定制它的存儲(chǔ)屬性媳否。

兩段式初始化過程的使用讓初始化更加安全栅螟,同時(shí)在每個(gè)類的層級(jí)結(jié)構(gòu)給與了完備的靈活性。兩段式初始化過程可以防止屬性值在初始化之前被訪問篱竭,還可以防止屬性值被另一個(gè)初始化器意外地賦予不同的值力图。

注意

Swift 的兩段式初始化過程與 Objective-C 的初始化類似。主要的不同點(diǎn)是在第一階段室抽,Objective-C 為每一個(gè)屬性分配零或空值(例如 0 或 nil )搪哪。Swift 的初始化流程更加靈活,它允許你設(shè)置自定義的初始值坪圾,并可以自如應(yīng)對(duì) 0 或 nil 不為合法值的情況晓折。

Swift編譯器執(zhí)行四種有效的安全檢查來確保兩段式初始化過程能夠順利完成:

安全檢查 1

指定初始化器必須保證在向上委托給父類初始化器之前,其所在類引入的所有屬性都要初始化完成兽泄。

如上所述漓概,一個(gè)對(duì)象的內(nèi)存只有在其所有儲(chǔ)存型屬性確定之后才能完全初始化。為了滿足這一規(guī)則病梢,指定初始化器必須保證它自己的屬性在它上交委托之前先完成初始化胃珍。

安全檢查 2

指定初始化器必須先向上委托父類初始化器梁肿,然后才能為繼承的屬性設(shè)置新值。如果不這樣做觅彰,指定初始化器賦予的新值將被父類中的初始化器所覆蓋吩蔑。

安全檢查 3

便捷初始化器必須先委托同類中的其它初始化器,然后再為任意屬性賦新值(包括同類里定義的屬性)填抬。如果沒這么做烛芬,便捷構(gòu)初始化器賦予的新值將被自己類中其它指定初始化器所覆蓋。

安全檢查 4

初始化器在第一階段初始化完成之前飒责,不能調(diào)用任何實(shí)例方法赘娄、不能讀取任何實(shí)例屬性的值,也不能引用 self 作為值宏蛉。

直到第一階段結(jié)束類實(shí)例才完全合法遣臼。屬性只能被讀取,方法也只能被調(diào)用拾并,直到第一階段結(jié)束的時(shí)候揍堰,這個(gè)類實(shí)例才被看做是合法的。

以下是兩段初始化過程辟灰,基于上述四種檢查的流程:

階段 1
  • 指定或便捷初始化器在類中被調(diào)用个榕;
  • 為這個(gè)類的新實(shí)例分配內(nèi)存。內(nèi)存還沒有被初始化芥喇;
  • 這個(gè)類的指定初始化器確保所有由此類引入的存儲(chǔ)屬性都有一個(gè)值∥鞑桑現(xiàn)在這些存儲(chǔ)屬性的內(nèi)存被初始化了;
  • 指定初始化器上交父類的初始化器為其存儲(chǔ)屬性執(zhí)行相同的任務(wù)继控;
    *這個(gè)調(diào)用父類初始化器的過程將沿著初始化器鏈一直向上進(jìn)行械馆,直到到達(dá)初始化器鏈的最頂部;
  • 一旦達(dá)了初始化器鏈的最頂部武通,在鏈頂部的類確保所有的存儲(chǔ)屬性都有一個(gè)值霹崎,此實(shí)例的內(nèi)存被認(rèn)為完全初始化了,此時(shí)第一階段完成冶忱。
階段 2
  • 從頂部初始化器往下尾菇,鏈中的每一個(gè)指定初始化器都有機(jī)會(huì)進(jìn)一步定制實(shí)例。初始化器現(xiàn)在能夠訪問 self 并且可以修改它的屬性囚枪,調(diào)用它的實(shí)例方法等等派诬;
  • 最終,鏈中任何便捷初始化器都有機(jī)會(huì)定制實(shí)例以及使用 slef 链沼。

自動(dòng)初始化器的繼承

子類默認(rèn)不會(huì)繼承父類初始化器默赂。總之括勺,在特定的情況下父類初始化器是可以被自動(dòng)繼承的缆八。實(shí)際上曲掰,這意味著在許多場(chǎng)景中你不必重寫父類初始化器,只要可以安全操作奈辰,你就可以毫不費(fèi)力地繼承父類的初始化器栏妖。

假設(shè)你為你子類引入的任何新的屬性都提供了默認(rèn)值,請(qǐng)遵守以下2個(gè)規(guī)則:

規(guī)則1

  • 如果你的子類沒有定義任何指定初始化器冯挎,它會(huì)自動(dòng)繼承父類所有的指定初始化器底哥。

規(guī)則2

  • 如果你的子類提供了所有父類指定初始化器的實(shí)現(xiàn)——要么是通過規(guī)則1繼承來的咙鞍,要么通過在定義中提供自定義實(shí)現(xiàn)的——那么它自動(dòng)繼承所有的父類便捷初始化器房官。

就算你的子類添加了更多的便捷初始化器,這些規(guī)則仍然適用续滋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翰守,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子疲酌,更是在濱河造成了極大的恐慌蜡峰,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朗恳,死亡現(xiàn)場(chǎng)離奇詭異湿颅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)粥诫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門油航,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怀浆,你說我怎么就攤上這事。” “怎么了砌滞?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵歇父,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我沙合,道長(zhǎng)奠伪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任首懈,我火速辦了婚禮绊率,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猜拾。我一直安慰自己即舌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布挎袜。 她就那樣靜靜地躺著顽聂,像睡著了一般肥惭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上紊搪,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天蜜葱,我揣著相機(jī)與錄音,去河邊找鬼耀石。 笑死牵囤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滞伟。 我是一名探鬼主播揭鳞,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼梆奈!你這毒婦竟也來了野崇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤亩钟,失蹤者是張志新(化名)和其女友劉穎乓梨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體清酥,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扶镀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了焰轻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臭觉。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鹦马,靈堂內(nèi)的尸體忽然破棺而出胧谈,到底是詐尸還是另有隱情,我是刑警寧澤荸频,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布菱肖,位于F島的核電站,受9級(jí)特大地震影響旭从,放射性物質(zhì)發(fā)生泄漏稳强。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一和悦、第九天 我趴在偏房一處隱蔽的房頂上張望退疫。 院中可真熱鬧,春花似錦鸽素、人聲如沸褒繁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棒坏。三九已至燕差,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坝冕,已是汗流浹背徒探。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喂窟,地道東北人测暗。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像磨澡,于是被迫代替她去往敵國(guó)和親碗啄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔钱贯,今天18年5月份再次想寫文章挫掏,發(fā)現(xiàn)簡(jiǎn)書還為我保存起的...
    Jenaral閱讀 2,756評(píng)論 2 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)秩命,斷路器,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • 官方文檔 初始化 Initialization是為準(zhǔn)備使用類褒傅,結(jié)構(gòu)體或者枚舉實(shí)例的一個(gè)過程弃锐。這個(gè)過程涉及了在實(shí)例里...
    hrscy閱讀 1,136評(píng)論 0 1
  • 1.1緒論 考試流程 打分方式 *E-rater(Structure,Grammar,etc.)*2-4 Huma...
    大屈子_59ec閱讀 279評(píng)論 0 0
  • 今天第一次發(fā)文到簡(jiǎn)書霹菊,其實(shí)發(fā)的沒啥內(nèi)容,就是還有一百天就考研了支竹,也總想來個(gè)考研百天倒計(jì)時(shí)旋廷。 我高考一百天的...
    毛科科閱讀 209評(píng)論 1 0