[譯] Objective-C init:為什么避免向 self 發(fā)消息會(huì)有幫助?

我有時(shí)會(huì)告訴自己成畦。我們的類也經(jīng)常這樣做。但在 Objective-C 中涝开,有幾個(gè)地方這樣做是有風(fēng)險(xiǎn)的:initdealloc循帐。

本文是Objective-C 中的代碼氣味系列文章中的一篇。

在 Objective-C 的 initdealloc 代碼中舀武,我經(jīng)尘逶。看到這樣的代碼。我舉一個(gè)簡(jiǎn)單的例子奕剃。你能找出問題所在嗎衷旅?

- (id)initWithFoo:(id)foo
{
    self = [super init];
    if (self)
        self.something = foo;
    return self;
}

- (void)dealloc
{
    self.something = nil;
    [super dealloc];
}

提示:是那些self.捐腿。它們?nèi)菀鬃屓苏`以為是簡(jiǎn)單的作業(yè)。但請(qǐng)記住柿顶,點(diǎn)符號(hào)隱藏著信息茄袖。

讓我們避開點(diǎn)符號(hào),再試一次:

- (id)initWithFoo:(id)foo
{
    self = [super init];
    if (self)
        [self setSomething:foo];
    return self;
}

- (void)dealloc
{
    [self setSomething:nil];
    [super dealloc];
}

現(xiàn)在你看到了嗎嘁锯?

當(dāng)給自己的信息有氣味的

向自己發(fā)送信息通常沒有問題宪祥。但有兩個(gè)地方要避免:

  • 創(chuàng)建對(duì)象時(shí),以及
  • 對(duì)象被銷毀時(shí)家乘。

在這兩個(gè)時(shí)間段蝗羊,物體處于一種有趣的、介于兩者之間的狀態(tài)仁锯。它缺乏完整性耀找。在這兩個(gè)時(shí)間段調(diào)用方法是一種代碼缺陷。為什么呢业崖?因?yàn)槊總€(gè)方法在對(duì)對(duì)象進(jìn)行操作時(shí)都應(yīng)保持不變野芒。下面是對(duì)象在方法中流動(dòng)時(shí)的自我一致性(self-consistency)概述:

  1. 開始:假設(shè)對(duì)象是自我一致性(self-consistency)的。
  2. 進(jìn)行中:對(duì)象狀態(tài)處于變化中双炕。
  3. 結(jié)束:恢復(fù)對(duì)象自我一致性(self-consistency)的不變性狞悲。

提示:不變性使你保持清醒。

我并沒有為此做出非常規(guī)的嘗試妇斤。蘋果公司有一份關(guān)于實(shí)用內(nèi)存管理的文檔摇锋,其中有一節(jié)的標(biāo)題是 "不要在初始化方法和 dealloc 中使用訪問方法"。

Don’t Use Accessor Methods in Initializer Methods and dealloc

The only places you shouldn’t use accessor methods to set an instance variable are in initializer methods and dealloc. To initialize a counter object with a number object representing zero, you might implement an init method as follows:

- init {
  self = [super init];
  if (self) {
      _count = [[NSNumber alloc] initWithInteger:0];
  }
  return self;
}

To allow a counter to be initialized with a count other than zero, you might implement an initWithCount: method as follows:

- initWithCount:(NSNumber *)startingCount {
   self = [super init];
   if (self) {
       _count = [startingCount copy];
   }
   return self;
}

Since the Counter class has an object instance variable, you must also implement a dealloc method. It should relinquish ownership of any instance variables by sending them a release message, and ultimately it should invoke super’s implementation:

- (void)dealloc {
   [_count release]站超;
   [super dealloc]荸恕;
}

Objective-C init/dealloc:拯救 ivars

解決方法很簡(jiǎn)單:在 Objective-C 的 initdealloc 方法中,直接訪問實(shí)例變量顷编,而不是通過屬性。在非 ARC 代碼中剑刑,檢查屬性屬性是否保留或分配媳纬。然后編寫與直接訪問相匹配的代碼。例如施掏,如果某個(gè)屬性是保留屬性钮惠,默認(rèn)支持 ivar _something,那么我們的代碼就會(huì)變成:

- (id)initWithFoo:(id)foo
{
    self = [super init];
    if (self)
       _something = [foo retain];
    return self;
}

- (void)dealloc
{
    [_something release];
    [super dealloc];
}

在 init/dealloc 中向 self 發(fā)送信息時(shí)仍能正常工作

在說過 "避免在 initdealloc 中向 self 發(fā)送信息 "之后七芭,我現(xiàn)在想緩和一下這種說法素挽。畢竟有兩個(gè)地方是可以這樣做的:

  • init 階段的最后階段,以及
  • 在 dealloc 開始時(shí)

這是因?yàn)樵谶@兩個(gè)地方狸驳,對(duì)象具有自一致性( self-consistency)预明。在 init 中缩赛,所有 ivars 都已建立。在 dealloc 中撰糠,沒有一個(gè) ivars 被銷毀酥馍。

但您仍需謹(jǐn)慎行事,并認(rèn)識(shí)到自己在對(duì)象生命周期中的位置阅酪。僅僅創(chuàng)建一個(gè)對(duì)象并不能開始任何繁重的工作旨袒。創(chuàng)建和銷毀都要輕便快捷。

譯自 Jon Reid 的 Objective-C init: Why It’s Helpful to Avoid Messages to self
侵刪

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末术辐,一起剝皮案震驚了整個(gè)濱河市砚尽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辉词,老刑警劉巖必孤,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異较屿,居然都是意外死亡隧魄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門隘蝎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來购啄,“玉大人,你說我怎么就攤上這事嘱么∈ê” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵曼振,是天一觀的道長(zhǎng)几迄。 經(jīng)常有香客問我,道長(zhǎng)冰评,這世上最難降的妖魔是什么映胁? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮甲雅,結(jié)果婚禮上解孙,老公的妹妹穿的比我還像新娘。我一直安慰自己抛人,他們只是感情好弛姜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妖枚,像睡著了一般廷臼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天荠商,我揣著相機(jī)與錄音寂恬,去河邊找鬼。 笑死结啼,一個(gè)胖子當(dāng)著我的面吹牛掠剑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播郊愧,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼朴译,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了属铁?” 一聲冷哼從身側(cè)響起眠寿,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焦蘑,沒想到半個(gè)月后盯拱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡例嘱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年狡逢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拼卵。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奢浑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腋腮,到底是詐尸還是另有隱情雀彼,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布即寡,位于F島的核電站徊哑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏聪富。R本人自食惡果不足惜莺丑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望墩蔓。 院中可真熱鬧梢莽,春花似錦、人聲如沸钢拧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽源内。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膜钓,已是汗流浹背嗽交。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颂斜,地道東北人夫壁。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像沃疮,于是被迫代替她去往敵國(guó)和親盒让。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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