本文為私人學(xué)習(xí)筆記览濒,僅僅做為記錄使用浦妄,詳情內(nèi)容請查閱 中文官方文檔厨喂。
屬性
- 屬性包裝器
屬性包裝器在管理如何存儲和定義屬性的代碼之前添加了一個(gè)分隔層。舉個(gè)例子奴烙,如果你想要對屬性進(jìn)行線程安全地存取助被,那你勢必要在所有存取的地方編寫相同的代碼進(jìn)行線程安全管理,是不是非常的麻煩切诀?屬性包裝器則幫你實(shí)現(xiàn)一次編寫揩环,終身復(fù)用的效果。
定義一個(gè)屬性包裝器趾牧,你需要創(chuàng)建一個(gè)具有 warppedValue
屬性的結(jié)構(gòu)體检盼、枚舉或者類。這個(gè) warppedValue
屬性就是包裝器需要的包裝屬性翘单。
定義一個(gè) TwelveOrLess
結(jié)構(gòu)體吨枉,確保包裝器所修飾的屬性存儲的值都是小于或等于 12 的數(shù)字。
@propertyWrapper
struct TwelveOrLess {
private var number: Int
init() { self.number = 0 }
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
你現(xiàn)在可以在屬性前面寫上包裝器哄芜,將包裝器作為特性的方式來使用貌亭。
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
// 打印 "0"
rectangle.height = 10
print(rectangle.height)
// 打印 "10"
rectangle.height = 24
print(rectangle.height)
// 打印 "12"
上述過程中,當(dāng)你操作 rectangle 的屬性進(jìn)行讀寫時(shí)认臊,都會經(jīng)過包裝器 wrappedValue
屬性的讀寫圃庭。編譯器將會合成包裝器所提供的存儲空間和訪問屬性的代碼。過程就像下面這樣失晴。
struct SmallRectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { return _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
- 類型屬性
類型屬性存儲的數(shù)據(jù)為共享數(shù)據(jù)剧腻。存儲型類型屬性可以是常量也可以是變量,但是計(jì)算型類型屬性和實(shí)例的計(jì)算型屬性一樣涂屁,只能定義成變量屬性书在。
需要注意的是,由于類型本身并沒有構(gòu)造器拆又,也就無法在初始化過程中為類型屬性賦值儒旬,因此必須給存儲型類型屬性指定默認(rèn)值。存儲型類型屬性是延遲初始化的帖族,它們只有在第一次被訪問時(shí)才被初始化栈源。即使它們被多個(gè)線程同時(shí)訪問,系統(tǒng)也保證智慧對其進(jìn)行一次初始化竖般,并且不需要對其使用 lazy
修飾符甚垦。這種特性也保證了對內(nèi)存的優(yōu)化。
方法
結(jié)構(gòu)體和枚舉能夠定義方法是 Swift 和 OC 的主要區(qū)別之一。
- mutating 可變方法
和類不同制轰,值類型的結(jié)構(gòu)體和枚舉默認(rèn)情況下前计,其屬性不能夠修改,但是你確實(shí)需要修改時(shí)垃杖,可以為方法添加 可變 mutating
行為男杈。
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
}
- 類型方法
和 OC 一樣,類型方法屬于類本身调俘。有兩種方式定義類型方法伶棒,func
前添加 static
或 class
,后者允許子類重寫彩库。類型方法位于方法體 {}
中的最前面肤无,作用域?qū)儆谠擃惖姆秶?/p>
- self 屬性
在實(shí)例方法中,self
屬性指向?qū)嵗旧砗眨憧梢允褂?self
來引用當(dāng)前實(shí)例宛渐,當(dāng)然 Swift
并不推薦使用它,self
的使用場景主要是在實(shí)例方法的某個(gè)參數(shù)名和實(shí)例的屬性名重復(fù)時(shí)眯搭,用 self
區(qū)分參數(shù)還是屬性窥翩,否則,參數(shù)優(yōu)先鳞仙,兩個(gè)都被認(rèn)為是參數(shù)名寇蚊。
struct Point {
var x = 0.0, y = 0.0
func isToTheRightOf(x: Double) -> Bool {
return self.x > x
}
}
在類型方法中,self
屬性指向類本身棍好,而不是該類型的某個(gè)實(shí)例仗岸。一般來說,在類型方法的方法體中借笙,可以直接通過類型方法的名稱調(diào)用本類中的其他類型方法扒怖,而不需要在方法名稱前面加上類型名,類似的业稼,類型屬性也同樣可以通過名稱直接訪問其他類型屬性姚垃,而不需要前面加上本類的類名。
下標(biāo)
快捷訪問集合盼忌、列表或序列中的元素而不需要使用存取方法,可以定義在類掂墓、結(jié)構(gòu)體和枚舉中谦纱。下標(biāo)不限于一維。
- subscript
subscript(index: Int) -> Int {
get {
// 返回一個(gè)適當(dāng)?shù)?Int 類型的值
}
set(newValue) {
// 執(zhí)行適當(dāng)?shù)馁x值操作
}
}
示例
struct Collection {
let data : [Any]
subscript(index: Int) -> Any? {
get {
if index < data.count {
return data[index]
} else {
return nil
}
}
}
}
let cc = Collection(data : ["0","1","2","3"])
print(cc[1] ?? "無")
- 類型下標(biāo)
類似類型方法君编,通過 static
或 class
來定義類型下標(biāo)跨嘉,后者可以重寫。
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
static subscript(n: Int) -> Planet {
return Planet(rawValue: n)!
}
}
let mars = Planet[4]
print(mars)
繼承
繼承和引用特性是區(qū)分類和結(jié)構(gòu)體吃嘿、枚舉的基本特征祠乃。Swift 中的類不需要像 OC 中從一個(gè)通用的 NSObject
基類繼承而來梦重。不繼承其他類的類,稱之為基類亮瓷。
- 重寫屬性的 Getters 和 Setters
重寫的屬性的限制不變小琴拧,即:可以將一個(gè)繼承來的只讀屬性重寫為一個(gè)讀寫屬性,也可以將讀寫屬性重寫為一個(gè)只讀屬性嘱支。另外蚓胸,如果你在重寫屬性中提供來了setter
,那么你一定要提供對應(yīng)的 getter
除师,反之沒有限制沛膳。
- 屬性觀察器
可以通過重寫屬性為一個(gè)繼承來的屬性添加屬性觀察器。這樣一來汛聚,無論被繼承屬性原本是如何實(shí)現(xiàn)的锹安,當(dāng)其屬性值發(fā)生改變時(shí),你就會被通知到倚舀。
無論是存儲類型還是計(jì)算類型的屬性都可以添加屬性觀察器叹哭,但是依舊有限制,那些常量存儲類型或者只讀計(jì)算類型屬性無法添加瞄桨,因?yàn)檫@些值是不可以被改變的话速,為它們設(shè)置 willSet
和 didSet
是不太恰當(dāng)?shù)牟僮鳎硗庑窘模瑢傩杂^察器和 setter
是不能同時(shí)存在的泊交,因?yàn)?setter
本身就已經(jīng)可以觀察到屬性的變化了。
- final
final
關(guān)鍵字來限制被重寫柱查、繼承廓俭,這意味著被修飾的屬性、方法或者類都是最終類型唉工。例如:final var
研乒、final func
、final class func
以及 final subscript
淋硝。
構(gòu)造過程
設(shè)置實(shí)例存儲屬性的初始值和執(zhí)行其他必須的設(shè)置或構(gòu)造過程雹熬。
你可以在構(gòu)造器中為存儲類屬性設(shè)置初始值,或者在定義屬性時(shí)分配默認(rèn)值谣膳。(這兩種方式是直接設(shè)置的竿报,不會觸發(fā)任何屬性觀察者)
// 構(gòu)造器中設(shè)置初始值
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
// 默認(rèn)屬性值
struct Fahrenheit {
var temperature = 32.0
}
- 構(gòu)造過程中常量屬性賦值
你可以在構(gòu)造過程中的任意時(shí)間點(diǎn)給常量屬性賦值,只要在構(gòu)造過程結(jié)束時(shí)特設(shè)置成確定的值继谚。一旦常量屬性被賦值烈菌,它將永遠(yuǎn)不可更改。
class SurveyQuestion {
let text: String
init(text: String) {
self.text = text // 常量屬性只能在定義它的類的構(gòu)成過程中修改,不能在其子類中修改
}
}
- 默認(rèn)構(gòu)造器
如果結(jié)構(gòu)體或類為所有屬性提供類默認(rèn)值芽世,又沒有提供任何自定義的構(gòu)造器挚赊,那么 Swift 會給這些結(jié)構(gòu)體或類提供一個(gè)默認(rèn)構(gòu)造器。這個(gè)默認(rèn)構(gòu)造器將簡單地創(chuàng)建一個(gè)所有屬性值都設(shè)置為它們默認(rèn)值的實(shí)例济瓢。
- 結(jié)構(gòu)體的逐一成員構(gòu)造器
結(jié)構(gòu)體如果沒有定義任何自定義構(gòu)造器荠割,它們將自動獲得一個(gè)逐一成員構(gòu)造器(memberwise initializer)。不像默認(rèn)構(gòu)造器葬荷,即使存儲型屬性沒有默認(rèn)值涨共,結(jié)構(gòu)體也能獲得逐一成員構(gòu)造器。
struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
- 值類型的構(gòu)造器代理
構(gòu)造器可以通過調(diào)用其他構(gòu)造器來完成實(shí)例的部分構(gòu)造過程宠漩,這一過程稱為構(gòu)造器代理举反,它能避免過個(gè)構(gòu)造器間的代碼重復(fù)。
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
}
如果你為某個(gè)值類型定了一個(gè)自定義的構(gòu)造器扒吁,你將無法訪問到默認(rèn)構(gòu)造器(如果是結(jié)構(gòu)體火鼻,還將無法反問逐一成員構(gòu)造器)。這種限制避免了在一個(gè)更復(fù)雜的構(gòu)造器中做了額外的重要設(shè)置雕崩,但是使用的人不小心使用自動生成的構(gòu)造器而導(dǎo)致錯(cuò)誤的情況魁索。
如果你仍然希望默認(rèn)構(gòu)造器、逐一成員構(gòu)造器以及自定義構(gòu)造器都能用來創(chuàng)建實(shí)例盼铁,那可以將自定義的構(gòu)造器寫到擴(kuò)展(extension)中粗蔚,而不是寫在值類型的原始定義中。
類的繼承和構(gòu)造過程
類中的所有存儲屬性(包括所有繼承自父類的屬性)都必須在構(gòu)造過程中設(shè)置初始值饶火。
Swift 為類提供類兩種構(gòu)造器來確保實(shí)例中所有存儲屬性都能獲得初始值:指定構(gòu)造器和便利構(gòu)造器鹏控。
每一個(gè)類都必須至少擁有一個(gè)指定的構(gòu)造器。便利構(gòu)造器是類中比較次要的肤寝、輔助性的構(gòu)造器当辐。你可以定義便利構(gòu)造器來調(diào)用同一個(gè)類中的指定構(gòu)造器,并為部分形參提供默認(rèn)值鲤看。你也可以定義便利構(gòu)造器來創(chuàng)建一個(gè)特殊用途或特定輸入值的實(shí)例缘揪。
// 指定構(gòu)造器
init(parameters) {
statements
}
// 便利構(gòu)造器
convenience init(parameters) {
statements
}
- 類構(gòu)造器代理
Swfit 構(gòu)造器之間的代理調(diào)用遵循三條規(guī)則:
- 指定構(gòu)造器必須調(diào)用其直接父類的指定構(gòu)造器
- 便利構(gòu)造器必須調(diào)用同類中定義的其他構(gòu)造器
- 便利構(gòu)造器最后必須調(diào)用指定構(gòu)造器
即:指定構(gòu)造器必須總是向上(父類)代理,便利構(gòu)造器必須總是橫向(同類)代理义桂。
- 構(gòu)造器的繼承和重寫
指定構(gòu)造器
當(dāng)你編寫一個(gè)和父類中指定構(gòu)造器相匹配的子類構(gòu)造器時(shí)找筝,你實(shí)際上是在重寫父類的這個(gè)指定構(gòu)造器。因此慷吊,你必須在定義子類構(gòu)造器時(shí)帶上 override
修飾符呻征,該修飾符會讓編譯器去檢查父類中是否有相匹配的指定構(gòu)造器,并驗(yàn)證構(gòu)造器參數(shù)是否被按照預(yù)想中被指定罢浇。
便利構(gòu)造器
如果你編寫了一個(gè)和父類便利構(gòu)造器相匹配的子類構(gòu)造器,由于子類不能直接調(diào)用父類的便利構(gòu)造器(構(gòu)造器代理規(guī)則中指出便利構(gòu)造器需要橫向調(diào)用其他構(gòu)造器),因此嚷闭,嚴(yán)格意義上來講攒岛,你的子類并未對一個(gè)父類構(gòu)造器提供重寫,因此你“重寫”一個(gè)父類便利構(gòu)造器時(shí)胞锰,不需要添加 override
修飾符灾锯。
子類可以在構(gòu)造過程中修改繼承來的變量屬性,但是不能修改繼承來的常量屬性嗅榕。
構(gòu)造器的自動繼承
子類在默認(rèn)情況下不會繼承父類的構(gòu)造器顺饮。但是如果滿足一定的條件,父類構(gòu)造器是可以被自動繼承的凌那,這意味著在許多常見場景你不必重寫父類的構(gòu)造器兼雄,并且可以在安全的情況下以最小的代價(jià)繼承父類的構(gòu)造器。
假如你為子類中引入的所有新屬性都提供了默認(rèn)值帽蝶,下面兩個(gè)規(guī)則將適用:
- 如果子類沒有定義任何指定構(gòu)造器赦肋,它將自動繼承父類所有的指定構(gòu)造器
- 如果子類提供了所有父類指定構(gòu)造器的實(shí)現(xiàn),它將自動繼承父類所有的便利構(gòu)造器
即使你在子類中添加了更多的便利構(gòu)造器励稳,這兩條規(guī)則仍然適用佃乘。
實(shí)例:
class Food {
var name: String
init(name: String) { // 指定構(gòu)造器
self.name = name
}
convenience init() { // 便利構(gòu)造器,需要橫向代理其他構(gòu)造器
self.init(name: "[Unnamed]")
}
}
下圖展示了 Food
的構(gòu)造器鏈:
class RecipeIngredient: Food {
var quantity: Int
init(name: String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
下圖展示了 RecipeIngredient
類的構(gòu)造器鏈:
RecipeIngredient
類擁有一個(gè)新的指定構(gòu)造器 init(name: String, quantity: Int)
用來設(shè)置新引入的屬性驹尼,在該構(gòu)造器中趣避,向上代理到父類的指定構(gòu)造器。
RecipeIngredient
也定義類一個(gè)便利構(gòu)造器新翎,init(name: String)
程帕,它橫向代理到本類中的指定構(gòu)造器,用來方便地創(chuàng)建 quantity
為 1 的實(shí)例料祠。另外骆捧,該便利構(gòu)造器使用了跟 Food
中指定構(gòu)造器 init(name: String)
相同的形參,因此這個(gè)便利構(gòu)造器重寫了父類的指定構(gòu)造器髓绽,前面需要使用修飾符 override
敛苇。
盡管 RecipeIngredient
將父類的指定構(gòu)造器重寫為了便利構(gòu)造器,但是它依然提供了父類所有的指定構(gòu)造器的實(shí)現(xiàn)顺呕,因此枫攀,RecipeIngredient
會自動繼承父類的所有便利構(gòu)造器。在 Food
中株茶,它的一個(gè)便利構(gòu)造器是 init()
来涨,這個(gè)會給 RecipeIngredient
繼承。它會代理到 RecipeIngredient
重寫的 init(name: String)
中启盛,接著代理到其他構(gòu)造器中蹦掐。
class ShoppingListItem: RecipeIngredient {
var purchased = false
var description: String {
var output = "\(quantity) x \(name)"
output += purchased ? " ?" : " ?"
return output
}
}
ShoppingListItem
為自己引入的所有屬性提供了默認(rèn)值技羔,并且沒有定義自己的任何構(gòu)造器,因此它將自動繼承所有父類中指定構(gòu)造器和便利構(gòu)造器卧抗。你可以使用其父類中的所有構(gòu)造器來創(chuàng)建實(shí)例藤滥。
下圖展示三個(gè)類的構(gòu)造器鏈:
- 可失敗的構(gòu)造器
所謂的失敗指的是給構(gòu)造器傳入類無效的形參,或者缺少某種所必須的外部資源而導(dǎo)致構(gòu)造失敗的情況社裆。
語法為在 init
關(guān)鍵字后面添加問號(init?
)拙绊。
可失敗構(gòu)造器會創(chuàng)建一個(gè)類型為自身類型的可選類型的對象。你通過 return nil
語句來表明可失敗構(gòu)造器在何種情況下應(yīng)該失敗泳秀。
嚴(yán)格來講标沪,Swift 的構(gòu)造器都不支持返回值,因?yàn)闃?gòu)造器本身的作用嗜傅,只是為了確保對象能被正確的構(gòu)造金句。因此你只需要用 return nil
表明可失敗構(gòu)造器構(gòu)造失敗,而不要使用關(guān)鍵字 return
來表明構(gòu)造成功磺陡。
帶原始值的枚舉類型的可失敗構(gòu)造器
此種枚舉類型會自帶一個(gè)可失敗構(gòu)造器 init?(rawValue:)
趴梢,該可失敗構(gòu)造器有一個(gè)合適的原始值類型的參數(shù) rawValue
形參,找到匹配的原始值則構(gòu)造成功币他,否則構(gòu)造失敗坞靶。
enum TemperatureUnit: Character {
case Kelvin = "K", Celsius = "C", Fahrenheit = "F"
}
// 構(gòu)造成功
let fahrenheitUnit = TemperatureUnit(rawValue: "F")
// 構(gòu)造失敗
let unknownUnit = TemperatureUnit(rawValue: "X")
枚舉類型的可失敗構(gòu)造器
你可以通過一個(gè)或者多個(gè)形參的可失敗構(gòu)造器來獲取枚舉類型中特定的枚舉成員。
enum TemperatureUnit {
case Kelvin, Celsius, Fahrenheit
init?(symbol: Character) {
switch symbol {
case "K":
self = .Kelvin
case "C":
self = .Celsius
case "F":
self = .Fahrenheit
default:
return nil
}
}
}
// 可以正確獲取到枚舉值
let fahrenheitUnit = TemperatureUnit(symbol: "F")
// 將無法匹配蝴悉,構(gòu)造失敗
let unknownUnit = TemperatureUnit(symbol: "X")
構(gòu)成失敗的傳遞
類彰阴、結(jié)構(gòu)體、枚舉的可失敗構(gòu)造器可以橫向代理到它們自己的其他可失敗構(gòu)造器拍冠。類似的尿这,子類的可失敗構(gòu)造器也能向上代理到父類的可失敗構(gòu)造器。
class Product {
let name: String
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
class CartItem: Product {
let quantity: Int
init?(name: String, quantity: Int) {
if quantity < 1 { return nil }
self.quantity = quantity
super.init(name: name)
}
}
Product
類的構(gòu)造條件是 name
不為空庆杜,CartItem
類首先要保證 quantity
的常量存儲類型的屬性的值至少為 1射众,然后向上代理到父類,同樣要保證 name
的值不能為空晃财,兩個(gè)條件不滿足任意一個(gè)都會導(dǎo)致構(gòu)造失敗叨橱。
重寫可失敗構(gòu)造器
你可以在子類中可以重寫父類的可失敗構(gòu)造器。當(dāng)你重寫父類可失敗構(gòu)造器為非可失敗構(gòu)造器時(shí)断盛,需要對父類的可失敗構(gòu)造器進(jìn)行強(qiáng)制解包罗洗。
你可以將可失敗的構(gòu)造器重寫為非可失敗的構(gòu)造器,反過來則不可以
class Document {
var name: String?
// 該構(gòu)造器創(chuàng)建了一個(gè) name 屬性的值為 nil 的 document 實(shí)例
init() {}
// 該構(gòu)造器創(chuàng)建了一個(gè) name 屬性的值為非空字符串的 document 實(shí)例
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
子類將可失敗構(gòu)造器重寫為非可失敗構(gòu)造器:
class AutomaticallyNamedDocument: Document {
override init() {
super.init()
self.name = "[Untitled]"
}
override init(name: String) {
super.init()
if name.isEmpty {
self.name = "[Untitled]"
} else {
self.name = name
}
}
}
class UntitledDocument: Document {
override init() {
super.init(name: "[Untitled]")! // 提供默認(rèn)值钢猛,并強(qiáng)制解包
}
}
必要構(gòu)造器
在類的構(gòu)造器前添加 required
修飾符表明所有該類的子類都必須實(shí)現(xiàn)該構(gòu)造器:
class SomeClass {
required init() {
// 構(gòu)造器的實(shí)現(xiàn)代碼
}
}
在子類重寫父類的必要構(gòu)造器時(shí)伙菜,必須在子類的構(gòu)造器前也添加 required
修飾符,表明該構(gòu)造器要求也應(yīng)用于繼承鏈后面的子類命迈。在重寫父類中必要的指定構(gòu)造器時(shí)贩绕,不需要添加 override
修飾符:
class SomeSubclass: SomeClass {
required init() {
// 構(gòu)造器的實(shí)現(xiàn)代碼
}
}
如果子類繼承的構(gòu)造器能滿足必要構(gòu)造器的要求火的,則無須在子類中顯式提供必要構(gòu)造器的實(shí)現(xiàn)。
通過閉包或函數(shù)設(shè)置屬性的默認(rèn)值
如果某個(gè) 存儲型 屬性的默認(rèn)值需要一些自定義或者設(shè)置丧叽,你可以使用閉包或者全局函數(shù)為其提供定制的默認(rèn)值卫玖。每當(dāng)某個(gè)屬性所在類型的新實(shí)例被構(gòu)造時(shí),那么對應(yīng)的閉包或者函數(shù)會被調(diào)用踊淳,而它們返回值會當(dāng)作默認(rèn)值賦值給這個(gè)屬性。
class SomeClass {
let someProperty: SomeType = {
// 在這個(gè)閉包中給 someProperty 創(chuàng)建一個(gè)默認(rèn)值
// someValue 必須和 SomeType 類型相同
return someValue
}()
}
當(dāng) SomeClass
類實(shí)例化時(shí)陕靠, 屬性 someProperty
后的閉包會被調(diào)用迂尝,注意花括號后面的一對小括號,這使用告訴 Swift 立即執(zhí)行此閉包剪芥,如果忽略了這對括號垄开,相當(dāng)于將閉包本身作為值賦值給了屬性,而不是將閉包的返回值賦值給屬性税肪。
如果你使用閉包來初始化屬性溉躲,請記住在閉包執(zhí)行時(shí),實(shí)例的其他部分都還沒有初始化益兄。這意味著你不能在閉包里訪問其他屬性锻梳,即使這些屬性有默認(rèn)值。同樣净捅,你也不能使用隱式的 self
屬性疑枯,或者調(diào)用任何實(shí)例方法。
如果你依舊想使用 self
屬性蛔六,或者調(diào)用其他實(shí)例方法荆永,你可以使用懶加載的形式,通過關(guān)鍵字 lazy
來創(chuàng)建国章。之所以可以使用其他屬性或者實(shí)例方法具钥,是因?yàn)樵搶傩砸呀?jīng)是在類實(shí)例化之后才被調(diào)用,實(shí)例中的屬性都已經(jīng)被初始化液兽,所以可以使用骂删。
lazy var someProperty: SomeType = {
// 在這個(gè)閉包中給 someProperty 創(chuàng)建一個(gè)默認(rèn)值
// someValue 必須和 SomeType 類型相同
// 可以使用 self 等實(shí)例屬性或方法
return someValue
}()
析構(gòu)過程
析構(gòu)器只適用于類,當(dāng)一個(gè)類的實(shí)例被釋放之前抵碟,析構(gòu)器會被立即調(diào)用桃漾。析構(gòu)器用關(guān)鍵字 deinit
來標(biāo)記。
deinit {
// 執(zhí)行析構(gòu)過程
}
Swift 會自動釋放不再需要的實(shí)例以釋放資源拟逮。通常不需要你手動去清理撬统,但是,當(dāng)你需要進(jìn)行額外的清理時(shí)敦迄,你則可能需要使用到析構(gòu)器恋追。
析構(gòu)器是被自動調(diào)用的凭迹,你不能主動調(diào)用析構(gòu)器。子類繼承了父類的析構(gòu)器苦囱,并且在子類析構(gòu)器實(shí)現(xiàn)的最后嗅绸,父類的析構(gòu)器依然會被自動調(diào)用。即使子類沒有提供自己的析構(gòu)器撕彤,父類的析構(gòu)器也同樣會被調(diào)用鱼鸠。