?作為一枚iOS開發(fā)的新手菜鳥,最近掉了一個(gè)比較難查的坑柱恤,不過最終還是爬出來了数初,而且其實(shí)非常簡(jiǎn)單,把過程記錄一下?梗顺。
需求是要做一個(gè)輪播泡孩。我的處理方法是寫了個(gè) SwitchBanner 類。在 viewDidLoad 中
SwitchBanner* banner = [SwitchBanner initWithType:@"首頁(yè)" wrapper:wrapper];
[banner fetchNew];
大致的想法就是傳入一個(gè) UIView 作為容器來初始化寺谤,然后提供一個(gè)更新內(nèi)容的方法仑鸥。
fetchNew 方法里面會(huì)去拿數(shù)據(jù),然后重新把輪播畫出來变屁。
接著因?yàn)槲蚁M恳粠嬅纥c(diǎn)擊了之后能夠跳轉(zhuǎn)到相應(yīng)的界面眼俊。所以在 SwitchBanner 內(nèi)部的 render 方法中,對(duì)每一幀的視圖(這里使用 UIButton 來做)加了一個(gè)事件粟关。
[button addTarget:self action:@selector(itemTapped:)
forControlEvents:UIControlEventTouchUpInside];
看起來沒有什么問題(有經(jīng)驗(yàn)的同學(xué)內(nèi)心已經(jīng)在笑了)疮胖,運(yùn)行時(shí)候也可以正常的顯示,但是一旦點(diǎn)擊橫幅,就會(huì)出現(xiàn) EXC_BAD_ACCESS 的錯(cuò)誤澎灸,并且完全沒有上下文院塞,所以一頭霧水不知從何解決。
在網(wǎng)上搜索一番之后找到解決之道击孩。
首先在 Xcode 中打開 Product->Scheme->Edit Scheme迫悠,快捷鍵是?<。在 "Diagnostics" 標(biāo)簽中開啟 "Enable Zombie Objects" 選項(xiàng)巩梢,以及 "Malloc Stack" 選項(xiàng)创泄。EXC_BAD_ACCESS 的產(chǎn)生是由于向未被初始化、或者已經(jīng)被回收的內(nèi)存發(fā)送消息括蝠,通常大家遇到的都是后者鞠抑。
開啟 "Zombie Objects" 后,對(duì)象不會(huì)被真正釋放忌警,而是轉(zhuǎn)為一枚僵尸對(duì)象搁拙,這樣你就可以看看僵尸先生生前大概是個(gè)啥模樣。開啟之后法绵,錯(cuò)誤拋出的時(shí)候會(huì)在控制臺(tái)打印出如下信息
-[SwitchBanner performSelector:withObject:withObject:]:
message sent to deallocated instance 0x7f8cb9fa5550
"Malloc Stack" 選項(xiàng)可以讓系統(tǒng)把內(nèi)存分配的過程都記錄下來以便進(jìn)一步看問題箕速。開啟之后在拋出異常時(shí)就可以在控制臺(tái)使用下面的語句看到對(duì)象是如何被分配的了
command script import lldb.macosx.heap
malloc_info --stack-history 0x7f8cb9fa5550
好了,問題找到了朋譬,就是我們的 SwitchBanner 實(shí)例被回收了盐茎。原因很簡(jiǎn)單,因?yàn)樗窃?viewDidLoad 內(nèi)部定義的徙赢,方法執(zhí)行完畢自然就被回收了字柠。解決方式就是讓 viewController 將其作為屬性持有住就行了:
@property (nonatomic, strong) SwitchBanner* banner;
什么嘛,很簡(jiǎn)單嘛狡赐。問題解決之后記得把那兩個(gè)調(diào)試選項(xiàng)都關(guān)掉窑业,養(yǎng)成好習(xí)慣。
以上枕屉。