Consumed parameters

consumed這個單詞我并不能給出很準確的翻譯警检,在這篇文章中,我把Consumed parameters稱為耗用參數(shù),它在OC中有著獨特的應用場景邦尊。

https://clang.llvm.org/docs/AutomaticReferenceCounting.html#id7這份文檔中瘩缆,講解了ARC方面的知識关拒,我對Consumed parameters這一個小模塊有很大的疑問,因此在網(wǎng)上查了一些資料,雖然有了一個大概的了解着绊,但是還是有一些不太清楚的地方谐算。

我們先來看一個例子,這個例子來源于上邊的那份文檔:

void foo(__attribute((ns_consumed)) id x);
- (void) foo: (id) __attribute((ns_consumed)) x;

我們可以用__attribute((ns_consumed))來修飾某個函數(shù)或者方法的參數(shù)归露,但這只是表面上的看法洲脂,實際上,它并不是只作用于它修飾的某個參數(shù)剧包,而是作用于整個函數(shù)或方法恐锦。

它的一個限制是,只能修飾可retain的對象指針類型疆液,比如id, Class等等一铅,不能修飾int *這樣的類型。

上邊的兩行代碼表示foo被標記為consumed堕油。意味著該函數(shù)的被調(diào)用者希望得到一個+1 retain count的對象潘飘。聲明了這個屬性后,當傳入一個參數(shù)時掉缺,在函數(shù)調(diào)用前卜录,ARC會把對該參數(shù)做一次retain操作,在該函數(shù)結(jié)束后再對該參數(shù)做一次release操作眶明,這一過程很像函數(shù)對局部變量的操作暴凑。

到這里就產(chǎn)生了第一個疑問?

為什么要對傳入的參數(shù)做retain赘来,在結(jié)束時又release掉现喳?

這個跟參數(shù)的生命周期有關(guān),我們在函數(shù)中使用了參數(shù)犬辰,當然希望能夠得到這個參數(shù)的所有權(quán)嗦篱,并且希望該參數(shù)一直存活著。這個內(nèi)容我會在下邊的內(nèi)容中給出一定的解釋幌缝。在上邊的文檔中有這樣一段話:

Rationale
This formalizes direct transfers of ownership from a caller to a callee.
The most common scenario here is passing the self parameter to init, but it is
useful to generalize. Typically, local optimization will remove any extra retains 
and releases: on the caller side the retain will be merged with a +1 source, and on
the callee side the release will be rolled into the initialization of the parameter.

這段話指出灸促,上邊的操作直接從調(diào)用者到被調(diào)用者轉(zhuǎn)移了所有權(quán),最常見的一個場景就是傳遞self參數(shù)到init方法之中涵卵,這個內(nèi)容將是本文最重要的內(nèi)容浴栽。一般來說,局部的優(yōu)化會移除任何額外的retain和release操作轿偎,這句話的意思是說典鸡,在函數(shù)中,某些局部變量不一定都會十分嚴格的按照retain/release原則來進行操作坏晦。調(diào)用端將會進行一些必要的合并操作萝玷,而被調(diào)用端也會對參數(shù)做一些額外的操作嫁乘。

到這里,有了第二個疑問球碉?

在ARC中蜓斧,為什么selfinit方法中是一個consumed parameter?

這個問題我之前是不知道的睁冬,它來源于這個提問挎春。init方法被標記為ns_consumes_selfns_consumes_self說明在方法中遵循上邊講的原則豆拨,在方法調(diào)用之前先把self做retain操作搂蜓,結(jié)束時做release操作。

User *user = [[User alloc] init];

這是一行非常簡單的代碼辽装,在調(diào)用了alloc后就創(chuàng)建了一個User對象帮碰,這個可以在這篇回答中獲得證據(jù)。返回的對象的retain count等于1拾积,大家應該記得殉挽,凡是通過alloc/new/copy.etc生成的對象,retain count都會+1拓巧,那么在這里的init方法中:

self = [super init];
if (self) { ... } 
return self;

self首先被init的調(diào)用者做了一次retain操作斯碌,此時它的retain count為1,執(zhí)行完self = [super init];后肛度,它的retain count為2傻唾,直到init返回后,self做了一次release操作承耿,此時它的retain count為1冠骄。**這就完美保證了self在方法中是一直存活的,也保證了能夠返回一個retain count為1的對象加袋。

有興趣可以翻看這個提問中的回答的部分凛辣,那哥們說的很詳細,再說一點职烧,在以前的MRC時代扁誓,代碼可以這樣寫:

- (NSView *)view {
    //explicit retain-autorelease of +1 variable is +2 -> +1, guaranteed access or nil.
    return [[_view retain]autorelease];
}

為了正確返回某個對象,先retain再release蚀之。

因此在使用consumed的時候蝗敢,需要注意一下幾點:

  • 保證方法的接收者不能為null,因為在方法被調(diào)用之前足删,參會會做retain操作寿谴,這樣就帶來了內(nèi)存泄漏的問題
  • 傳遞的參數(shù)的個數(shù)不能大于方法能夠動態(tài)處理的個數(shù),否則可能引起未知的后果
  • 謹慎處理靜態(tài)類型的問題

何為靜態(tài)類型壹堰,何為動態(tài)類型拭卿?

A *a = [A new];
B *b = a;

那么b的靜態(tài)類型就是B,這個類型是由編譯器決定的贱纠,而A則是它的動態(tài)類型峻厚,由運行時決定。

我發(fā)現(xiàn)ASDisplayKit的源碼極其復雜谆焊,估計要花相當多的時間來解讀了惠桃。不能放棄,加油辖试。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辜王,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子罐孝,更是在濱河造成了極大的恐慌呐馆,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莲兢,死亡現(xiàn)場離奇詭異汹来,居然都是意外死亡,警方通過查閱死者的電腦和手機改艇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門收班,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谒兄,你說我怎么就攤上這事摔桦。” “怎么了承疲?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵邻耕,是天一觀的道長。 經(jīng)常有香客問我燕鸽,道長赊豌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任绵咱,我火速辦了婚禮碘饼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘悲伶。我一直安慰自己艾恼,他們只是感情好,可當我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布麸锉。 她就那樣靜靜地躺著钠绍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪花沉。 梳的紋絲不亂的頭發(fā)上柳爽,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天媳握,我揣著相機與錄音,去河邊找鬼磷脯。 笑死蛾找,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的赵誓。 我是一名探鬼主播打毛,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼俩功!你這毒婦竟也來了幻枉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤诡蜓,失蹤者是張志新(化名)和其女友劉穎熬甫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔓罚,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡罗珍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了脚粟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片覆旱。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖核无,靈堂內(nèi)的尸體忽然破棺而出扣唱,到底是詐尸還是另有隱情,我是刑警寧澤团南,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布噪沙,位于F島的核電站,受9級特大地震影響吐根,放射性物質(zhì)發(fā)生泄漏正歼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一拷橘、第九天 我趴在偏房一處隱蔽的房頂上張望局义。 院中可真熱鬧,春花似錦冗疮、人聲如沸萄唇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽另萤。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間四敞,已是汗流浹背泛源。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忿危,地道東北人达箍。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像癌蚁,于是被迫代替她去往敵國和親幻梯。 傳聞我的和親對象是個殘疾皇子兜畸,可洞房花燭夜當晚...
    茶點故事閱讀 43,576評論 2 349

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