??????? 說到導航的push,pop操作,想必寫代碼的我們基本每天都可能會用到,前兩天遇到一個問題,某些界面我需要pop到上級的上級界面,起初我的想法很簡單,那就是[[self.navigationController popViewControllerAnimated:NO].navigationController popViewControllerAnimated:YES];
??????? 但是沒效果,還是pop到上級界面了,并沒有pop到上級的上級界面,然后我想著這樣行不通,那得,我就用找到對應的那個controller,然后pop到這個界面:
UIViewController *target = nil;
for (UIViewController * controller in self.navigationController.viewControllers) {
???????? if ([controller isKindOfClass:[YourViewControllerName class]]) {
???????????????????? target = controller;
???????? }
}
if (target) {
??????? [self.navigationController popToViewController:target animated:YES];
}
?????? 當然了,這樣也是解決問題了,但是我后來在review代碼的時候,總感覺這樣很累贅,沒道理嘛,簡單的一個出棧操作,肯定是簡單的pop就可以搞定的啊,然后我細心考量了下我之前的哪行pop代碼。What a fuck man! 原來是這樣,[[self.navigationController popViewControllerAnimated:NO].navigationController popViewControllerAnimated:YES];
?????? 我們先看第一行[self.navigation popViewControllerAnimated:NO],這是把當前的ViewController從當前棧中做pop操作,會從當前棧中移除,那會發生什么問題呢?問題就是當前的VC被銷毀了,然后接著看后邊的代碼 .navagationViewController,肯定就沒有什么意義了啊,不用說肯定是nil啊,我們對nil對象發送一個消息指令,objc_msgSend(object, SEL op, ...),對啊,object都是nil了,發消息指令還有用嗎?
解決方法:
?????? 我們需要在這個VC pop之前先把當前的navigationController保存下來,然后利用這個導航做兩個pop操作即可!可以像下邊這樣修改上邊的代碼:
??????????????? UINavigationController *nav = self.navigationController;
??????????????? [self.navigationController popViewControllerAnimated:NO];
??????????????? [nav popViewControllerAnimated:YES];
?????? 我們蘋果的runtime在給nil發送指令的時候是不會crash的,但是在對一個存在的對象發送一個此對象沒有對應的消息指令的時候是會crash的,所以雖然說給nil發送指令(nil調方法)不會crash,但是真要是有這種bug出現的時候其實還是不好找的,切記:判斷對象是否為nil是很有必要的!