ASSOCIATED OBJECT 對(duì)象關(guān)聯(lián)

王巍 (@ONEVCAT) 發(fā)布于 2016-04-27

不知道是從什么時(shí)候開(kāi)始,“是否能通過(guò) Category 給已有的類(lèi)添加成員變量” 就成為了一道 Objective-C 面試中的常見(jiàn)題目。不幸的消息是這個(gè)面試題目在 Swift 中可能依舊會(huì)存在。
得益于 Objective-C 的運(yùn)行時(shí)和 Key-Value Coding 的特性,我們可以在運(yùn)行時(shí)向一個(gè)對(duì)象添加值存儲(chǔ)。而在使用 Category 擴(kuò)展現(xiàn)有的類(lèi)的功能的時(shí)候,直接添加實(shí)例變量這種行為是不被允許的,這時(shí)候一般就使用 property 配合 Associated Object 的方式,將一個(gè)對(duì)象 “關(guān)聯(lián)” 到已有的要擴(kuò)展的對(duì)象上。進(jìn)行關(guān)聯(lián)后,在對(duì)這個(gè)目標(biāo)對(duì)象訪問(wèn)的時(shí)候,從外界看來(lái),就似乎是直接在通過(guò)屬性訪問(wèn)對(duì)象的實(shí)例變量一樣,可以非常方便。
在 Swift 中這樣的方法依舊有效,只不過(guò)在寫(xiě)法上可能有些不同。兩個(gè)對(duì)應(yīng)的運(yùn)行時(shí)的 get 和 set Associated Object 的 API 是這樣的:
func objc_getAssociatedObject(object: AnyObject!, key: UnsafePointer<Void> ) -> AnyObject!func objc_setAssociatedObject(object: AnyObject!, key: UnsafePointer<Void>, value: AnyObject!, policy: objc_AssociationPolicy)

這兩個(gè) API 所接受的參數(shù)也都 Swift 化了,并且因?yàn)?Swift 的安全性,在類(lèi)型檢查上嚴(yán)格了不少,因此我們有必要也進(jìn)行一些調(diào)整。在 Swift 中向某個(gè) extension
里使用 Associated Object 的方式將對(duì)象進(jìn)行關(guān)聯(lián)的寫(xiě)法是:
// MyClass.swiftclass MyClass {}// MyClassExtension.swiftprivate var key: Void?extension MyClass { var title: String? { get { return objc_getAssociatedObject(self, &key) as? String } set { objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } }}// 測(cè)試func printTitle(input: MyClass) { if let title = input.title { print("Title: (title)") } else { print("沒(méi)有設(shè)置") }}let a = MyClass()printTitle(a)a.title = "Swifter.tips"printTitle(a)// 輸出:// 沒(méi)有設(shè)置// Title: Swifter.tips

key
的類(lèi)型在這里聲明為了 Void?
,并且通過(guò) &
操作符取地址并作為 UnsafePointer<Void>
類(lèi)型被傳入。這在 Swift 與 C 協(xié)作和指針操作時(shí)是一種很常見(jiàn)的用法。關(guān)于 C 的指針操作和這些 unsafe
開(kāi)頭的類(lèi)型的用法,可以參看 UnsafePointer 一節(jié)的內(nèi)容。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、隨機(jī)數(shù) 不需要隨機(jī)數(shù)種子 arc4random()%N + begin:產(chǎn)生begin~begin+N的隨機(jī)數(shù)...
    我是小胡胡123閱讀 4,406評(píng)論 0 2
  • Swift2.0 1.defer譯為延緩、推遲之意類(lèi)似棧 注意作用域,其次是調(diào)用順序——即一個(gè)作用域結(jié)束(注意),...
    zeqinjie閱讀 3,509評(píng)論 0 50
  • 問(wèn)題 1)柯里化,通過(guò)柯里化,改造target-action,因?yàn)閟elector只能使用字符串,在編譯時(shí)無(wú)法發(fā)現(xiàn)...
    lanjing閱讀 3,736評(píng)論 3 19
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,032評(píng)論 0 9
  • 和先生邊吃邊聊,談到了上帝。我談了我的理解,先生覺(jué)得很新奇,分享給大家。 我是一位醫(yī)學(xué)工作者,所以我用生物和微生物...
    葉彌兒閱讀 851評(píng)論 0 0

友情鏈接更多精彩內(nèi)容