Swift類型屬性驯用、單例

類型屬性(Static)

  • 線程安全的
  • 全局的
class LGTeacher {
   static var age: Int = 20
}
var age = LGTeacher.age

在SIL角度來剖析一下原理:
打開項(xiàng)目文件夾目錄

cd /Users/zhou/Desktop/SwiftTwoPractice/SwiftTwoPractice

把 mian.swift編譯成main.sil并打開(推薦使用vs code)

swiftc -emit-sil main.swift | xcrun swift-demangle >> ./main.sil && open main.sil
No application knows how to open /Users/zhou/Desktop/SwiftTwoPractice/SwiftTwoPractice/main.sil.

class LGTeacher {
  @_hasStorage @_hasInitialValue static var age: Int { get set }
  @objc deinit
  init()
}

@_hasStorage @_hasInitialValue var age: Int { get set }

// globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0
sil_global private @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0 : $Builtin.Word

// static LGTeacher.age
sil_global hidden @static main.LGTeacher.age : Swift.Int : $Int

// age
sil_global hidden @main.age : Swift.Int : $Int

LGTeacher類型屬性聲明的過程中多了sil_Global

// static LGTeacher.age
sil_global hidden @static main.LGTeacher.age : Swift.Int : $Int

這句話說明了當(dāng)前聲明的LGTeacher.age聲明的類型屬性變成了一個(gè)全局變量准验,變成了一個(gè)golbal缭嫡,接下來再看在賦值的過程中做了什么事情

// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  alloc_global @main.age : Swift.Int                   // id: %2
  %3 = global_addr @main.age : Swift.Int : $*Int       // user: %9
  %4 = metatype $@thick LGTeacher.Type
  // function_ref LGTeacher.age.unsafeMutableAddressor
  %5 = function_ref @main.LGTeacher.age.unsafeMutableAddressor : Swift.Int : $@convention(thin) () -> Builtin.RawPointer // user: %6
  %6 = apply %5() : $@convention(thin) () -> Builtin.RawPointer // user: %7
  %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Int // user: %8
  %8 = begin_access [read] [dynamic] %7 : $*Int   // users: %10, %9
  copy_addr %8 to [initialization] %3 : $*Int     // id: %9
  end_access %8 : $*Int                           // id: %10
  %11 = integer_literal $Builtin.Int32, 0         // user: %12
  %12 = struct $Int32 (%11 : $Builtin.Int32)      // user: %13
  return %12 : $Int32                             // id: %13
} // end sil function 'main'

第一點(diǎn)蛉加,當(dāng)我去訪問他的時(shí)候把%8給到了%3同衣,%3是聲明的全局age變量竟块,%8是怎么來的,%8是在%6處調(diào)用了函數(shù)%5得來的耐齐,讓我們?nèi)タ碄main.LGTeacher.age.unsafeMutableAddressor這個(gè)函數(shù)干了什么

// LGTeacher.age.unsafeMutableAddressor
sil hidden [global_init] @main.LGTeacher.age.unsafeMutableAddressor : Swift.Int : $@convention(thin) () -> Builtin.RawPointer {
bb0:
  %0 = global_addr @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0 : $*Builtin.Word // user: %1
  %1 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer // user: %3
  // function_ref globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0
  %2 = function_ref @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0 : $@convention(c) () -> () // user: %3
  %3 = builtin "once"(%1 : $Builtin.RawPointer, %2 : $@convention(c) () -> ()) : $()
  %4 = global_addr @static main.LGTeacher.age : Swift.Int : $*Int // user: %5
  %5 = address_to_pointer %4 : $*Int to $Builtin.RawPointer // user: %6
  return %5 : $Builtin.RawPointer                 // id: %6
} // end sil function 'main.LGTeacher.age.unsafeMutableAddressor : Swift.Int'

這這里里面它又執(zhí)行了我們?nèi)值姆椒ˊglobalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0浪秘,接著找到這個(gè)方法蒋情,

// globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0
sil private @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0 : $@convention(c) () -> () {
bb0:
  alloc_global @static main.LGTeacher.age : Swift.Int       // id: %0
  %1 = global_addr @static main.LGTeacher.age : Swift.Int : $*Int // user: %4
  %2 = integer_literal $Builtin.Int64, 20         // user: %3
  %3 = struct $Int (%2 : $Builtin.Int64)          // user: %4
  store %3 to %1 : $*Int                          // id: %4
  %5 = tuple ()                                   // user: %6
  return %5 : $()                                 // id: %6
} // end sil function 'globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0'

這個(gè)是全局的初始化方法,這個(gè)方法是為了初始化main.LGTeacher.age這個(gè)全局變量耸携,把20賦值給了當(dāng)前這個(gè)全局變量

需要注意的是:

在初始化的過程中棵癣,有一點(diǎn)的不一樣,在@main.LGTeacher.age.unsafeMutableAddressor 這個(gè)方法內(nèi)夺衍,出現(xiàn)了builtin "once"

%3 = builtin "once"(%1 : Builtin.RawPointer, %2 :@convention(c) () -> ()) : $()

如果通過斷點(diǎn)調(diào)試狈谊,這個(gè)builtin "once",調(diào)用的是swift_once,打開swift源碼找到Once.cpp會(huì)看到swift_once方法

/// Runs the given function with the given context argument exactly once.
/// The predicate argument must point to a global or static variable of static
/// extent of type swift_once_t.
void swift::swift_once(swift_once_t *predicate, void (*fn)(void *),
                       void *context) {
#if defined(__APPLE__)
  dispatch_once_f(predicate, context, fn);
#elif defined(__CYGWIN__)
  _swift_once_f(predicate, context, fn);
#else
  std::call_once(*predicate, [fn, context]() { fn(context); });
#endif
}
總結(jié):

看到這里就特別熟悉了沟沙,看到了GCD的dispatch_once_f河劝,證明了static只會(huì)初始化age這個(gè)變量一次,所以在這個(gè)過程中矛紫,相比較lazy來說赎瞎,static聲明的類型屬性有兩個(gè)方式,他是一個(gè)全局的颊咬,并且他是線程安全的煎娇!

swift單例

在OC中的單例寫法:

#import "FFManager.h"

@implementation FFManager

+ (instancetype)sharedInstance {
    static FFManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        sharedInstance = [[FFManager alloc]init];
    });
    return  sharedInstance;
}

@end

在swift中的單例寫法:

class FFManager {
    static let sharedInstance: FFManager = FFManager()
    private init() {}
}
總結(jié):

第一在這個(gè)里面給sharedInstance一個(gè)全局狀態(tài),第二給初始化方法init添加了訪問控制權(quán)限private贪染,這樣就完成了單例

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缓呛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子杭隙,更是在濱河造成了極大的恐慌哟绊,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痰憎,死亡現(xiàn)場(chǎng)離奇詭異票髓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铣耘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門洽沟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜗细,你說我怎么就攤上這事裆操。” “怎么了炉媒?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵踪区,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我吊骤,道長(zhǎng)缎岗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任白粉,我火速辦了婚禮传泊,結(jié)果婚禮上鼠渺,老公的妹妹穿的比我還像新娘。我一直安慰自己眷细,他們只是感情好拦盹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著薪鹦,像睡著了一般掌敬。 火紅的嫁衣襯著肌膚如雪惯豆。 梳的紋絲不亂的頭發(fā)上池磁,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音楷兽,去河邊找鬼地熄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛芯杀,可吹牛的內(nèi)容都是我干的端考。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼揭厚,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼却特!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筛圆,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤裂明,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后太援,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闽晦,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年提岔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仙蛉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碱蒙,死狀恐怖荠瘪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赛惩,我是刑警寧澤巧还,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站坊秸,受9級(jí)特大地震影響麸祷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜褒搔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一阶牍、第九天 我趴在偏房一處隱蔽的房頂上張望喷面。 院中可真熱鬧,春花似錦走孽、人聲如沸惧辈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盒齿。三九已至,卻和暖如春困食,著一層夾襖步出監(jiān)牢的瞬間边翁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國打工硕盹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留符匾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓瘩例,卻偏偏與公主長(zhǎng)得像啊胶,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子垛贤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

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