為什么不要在init和dealloc函數(shù)中使用accessor

前言
最近翻唐巧大神的Blog,發(fā)現(xiàn)其曾于2011年在Blog上發(fā)過一片文章–不要在init和dealloc函數(shù)中使用accessor吗跋,即調(diào)用get,set方法的點語法宁昭,相信絕大多數(shù)人都這么做過(包括我)酗宋。其中提到蘋果的開發(fā)者文檔中講解cocoa內(nèi)存管理的文章第16頁有一節(jié)的題目為:Don’t Use Accessor Methods in Initializer Methods and dealloc,可惜文檔也沒有說明原因寂曹。唐巧在搜尋了一些資料后并未得出確切結(jié)論回右,只是認(rèn)為一種說法比較靠譜——因為在 init 和 dealloc 中,對象的存在與否還不確定渺氧,所以給對象發(fā)消息可能不會成功蹬屹。事實上并非如此。
下為《禪與 Objective-C 編程藝術(shù)》的原文引用
objc創(chuàng)建對象的特性為兩步創(chuàng)建:
alloc
負(fù)責(zé)創(chuàng)建對象哩治,這個過程包括分配足夠的內(nèi)存來保存對象业筏,寫入 isa指針,初始化引用計數(shù)蒜胖,以及重置所有實例變量。
init
負(fù)責(zé)初始化對象寻狂,這意味著使對象處于可用狀態(tài)朋沮。這通常意味著為對象的實例變量賦予合理有用的值。

alloc
方法將返回一個有效的未初始化的對象實例樊拓。每一個對這個實例發(fā)送的消息會被轉(zhuǎn)換成一次objc_msgSend() 函數(shù)的調(diào)用,形參 self 的實參是 alloc 返回的指針蒂胞;這樣 self在所有方法的作用域內(nèi)都能夠被訪問条篷。 按照慣例蛤织,為了完成兩步創(chuàng)建鸿染,新創(chuàng)建的實例第一個被調(diào)用的方法將是 init方法。注意姚炕,NSObject 在實現(xiàn) init 時丢烘,只是簡單的返回了 self。

可見alloc完后就可以直接對對象發(fā)送消息了播瞳,不存在可能不成功的情況。所以接下來想和大家一起探討下為什么不能在init和dealloc中使用accessor忧侧。
原因
我認(rèn)為牌芋,不能在init和dealloc中使用accessor的原因是由于面向?qū)ο蟮睦^承、多態(tài)特性與accessor可能造成的副作用聯(lián)合導(dǎo)致的肯夏。繼承和多態(tài)導(dǎo)致在父類的實現(xiàn)中調(diào)用accessor可能導(dǎo)致調(diào)用到子類重寫的accessor犀暑,而此時子類部分并未完全初始化或已經(jīng)銷毀,導(dǎo)致原有的假設(shè)不成立,從而出現(xiàn)一系列的邏輯問題甚至崩潰桐磁。為了更清晰地闡述暇矫,以下分別從init和dealloc上舉例說明择吊。
Init example
BaseClass:

@interface BaseClass : NSObject

@property(nonatomic) NSString* info;

@end

@implementation BaseClass

- (instancetype)init {
  if ([super init]) {
      self.info = @"baseInfo";
  }
  return self;
}
@end

SubClass:

@interface SubClass : BaseClass

@end

@interface SubClass ()

@property (nonatomic) NSString* subInfo;

@end

@implementation SubClass

- (instancetype)init {
  if (self = [super init]) {
      self.subInfo = @"subInfo";
  }
  return self;
}

- (void)setInfo:(NSString *)info {
  [super setInfo:info];
  NSString* copyString = [NSString stringWithString:self.subInfo];
  NSLog(@"%@",copyString);
}
@end

當(dāng)執(zhí)行[[SubClass alloc]init]時會調(diào)用父類在Init方法。其中調(diào)用了accessor,去初始化父類部分的info屬性枉长。看起來十分正常必峰,但一旦子類重寫了該方法,那么由于多態(tài)此時調(diào)用的就是子類的accessor方法凭需!子類的accessor實現(xiàn)中的代碼都是以子類部分已初始化完全為前提編寫肝匆,即子類部分已經(jīng)初始化完畢,完全可用旗国,而現(xiàn)實情況是其init方法并沒有執(zhí)行完能曾,對此假設(shè)并不成立,從而可能造成崩潰寿冕。以上例子有人造的痕跡,現(xiàn)實中更多的是某個方法被少調(diào)用一次藻茂,出現(xiàn)邏輯錯誤曙蒸。
dealloc example

BaseClass:

@interface BaseClass : NSObject

@property(nonatomic) NSString* info;

@end

@implementation BaseClass

- (void)dealloc {
  self.info = nil;
}

@end

SubClass:

@interface SubClass : BaseClass

@property (nonatomic) NSString* debugInfo;

@end

@implementation SubClass

- (instancetype)init {
  if (self = [super init]) {
      _debugInfo = @"This is SubClass";
  }
  return self;
}

- (void)setInfo:(NSString *)info {
  NSLog(@"%@",[NSString stringWithString:self.debugInfo]);
}

- (void)dealloc {
  _debugInfo = nil;
}

@end

在SubClass的實例對象銷毀時,首先調(diào)用子類的dealloc肖油,再調(diào)用父類的dealloc臂港。如果父類在dealloc時調(diào)用了accessor 并且該accessor被子類重寫,就會調(diào)用到子類的accessor县袱。而此時子類的dealloc已經(jīng)被調(diào)用了佑力,基于其完整的假設(shè)已經(jīng)不成立,那么再執(zhí)行子類的代碼會存在一定風(fēng)險打颤,如上例就會崩潰漓滔。

結(jié)語

在init和dealloc中使用accessor是存在風(fēng)險的乖篷。即使現(xiàn)在代碼沒有問題,難保將來維護或擴展時會出現(xiàn)問題豁鲤。只有將蘋果所說的Don’t Use Accessor Methods in Initializer Methods and dealloc當(dāng)作一條編程規(guī)范鲸沮,才能從根本上規(guī)避這個問題。規(guī)矩立好了日熬,代碼欠的債就少肾胯,將來的生活就會更加美好。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毕荐,一起剝皮案震驚了整個濱河市艳馒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌第美,老刑警劉巖陆爽,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異别威,居然都是意外死亡驴剔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門豺妓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人科侈,你說我怎么就攤上這事。” “怎么了权薯?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵睡扬,是天一觀的道長。 經(jīng)常有香客問我屎开,道長马靠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任逞度,我火速辦了婚禮妙啃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘揖赴。我一直安慰自己,他們只是感情好渐北,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布腔稀。 她就那樣靜靜地躺著羽历,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秕磷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天疏尿,我揣著相機與錄音,去河邊找鬼锌俱。 笑死敌呈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的磕洪。 我是一名探鬼主播析显,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谷异!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寓落,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤伶选,失蹤者是張志新(化名)和其女友劉穎尖昏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抽诉,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡迹淌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了耙饰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纹份。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡廷痘,死狀恐怖件已,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兄猩,我是刑警寧澤鉴未,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響享怀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梅屉,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一鳞贷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惰聂,春花似錦咱筛、人聲如沸搓幌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至堂污,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敷鸦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工值依, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碟案,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓辆亏,卻偏偏與公主長得像鳖目,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子领迈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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