雖然入坑時曾經用Swift2.0寫過4個多月代碼,后來換公司項目又用OC了添怔,現(xiàn)在打算用Swift寫代碼了. OC->Swift->OC->Swift??
本想創(chuàng)建一個Struct單例
struct BannerQueue {
static let `default` = BannerQueue()
var banners: [Banner] = []
}
在其他地方多次使用 BannerQueue.default 時發(fā)現(xiàn) banners數(shù)組的值不一致广料,每次都是新建的數(shù)組。
查了下網上說結構體是值傳遞(在棧中)性昭,不能創(chuàng)建單例,每次調用都是一個新的對象汹族,類才行(值引用, 在堆中)其兴。
正確的單例方式:
class BannerQueue {
static let `default` = BannerQueue()
private init() {}
}
注意: 必須保證init方法的私有性,只有這樣榴徐,才能保證單例是真正唯一的匀归,避免外部對象通過訪問init方法創(chuàng)建單例類的其他實例。由于Swift中的所有對象都是由公共的初始化方法創(chuàng)建的穆端,我們需要重寫自己的init方法,并設置其為私有的攒巍。這很簡單,而且不會破壞到我們優(yōu)雅的單行單例方法柒莉。
以前在OC中創(chuàng)建單例,會用到dispatch_once鲤氢,或者直接用OC的直接移植版寫Swift單例西潘, 其實沒必要的,Swift這一句簡潔的代碼已經幫我們實現(xiàn)了dispatch_once相种,原因如下:
現(xiàn)在品姓,你可能會有疑問:為何看不到dispatch_once?根據Apple Swift博客中的說法腹备,以上方法都自動滿足dispatch_once規(guī)則。這里有個帖子可以證明dispatch_once規(guī)則一直在起作用镀岛。
“全局變量(還有結構體和枚舉體的靜態(tài)成員)的Lazy初始化方法會在其被訪問的時候調用一次友驮。類似于調用'dispatch_once'以保證其初始化的原子性。這樣就有了一種很酷的'單次調用'方式:只聲明一個全局變量和私有的初始化方法即可走越〕苌”--來自Apple's Swift Blog
(“The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched asdispatch_once
to make sure that the initialization is atomic. This enables a cool way to usedispatch_once
in your code: just declare a global variable with an initializer and mark it private.”)這就是Apple官方文檔給我們的所有信息,但這些已經足夠證明全局變量和結構體/枚舉體的靜態(tài)成員是支持”dispatch_once”特性的∽还梗現(xiàn)在算柳,我們相信使用全局變量來“懶包裝”單例的初始化方法到dispatch_once代碼塊中是100%安全的。