一個 VC 被提前釋放的莫名 BUG

BUG情景: 重復點擊TabBar中的某個 Item 后窟绷,當前頁面中的 UICollectionCell 點擊進入詳情頁面無效锯玛,日志顯示該詳情頁已經 Dealloc 掉了。兼蜈。攘残。

Home

類似點擊 重復點擊 Home 后,進入不了商品詳情頁啦...

GoodsDetailViewController *goodsDetailVC = [[GoodsDetailViewController alloc] init];
goodsDetailVC.goodsId = goodsModel.goodsId;
[self.viewController.navigationController pushViewController:goodsDetailVC animated:YES];

只要一點擊商品Cell为狸,日志就顯示:

GoodsDetailViewController->>>>已經釋放了

PS : 此處是用了一個 Runtime 實現(xiàn)的:

#import "UIViewController+Dealloc.h"
#import <objc/runtime.h>
@implementation UIViewController (Dealloc)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        Method setTextMethod = class_getInstanceMethod(class, NSSelectorFromString(@"dealloc"));
        Method replaceSetTextMethod = class_getInstanceMethod(class, NSSelectorFromString(@"pq_dealloc"));
        method_exchangeImplementations(setTextMethod, replaceSetTextMethod);
    });
}

- (void)pq_dealloc {
    NSLog(@"%@->>>>已經釋放了",[self class]);
    [self pq_dealloc];
}

@end

一下子很悶歼郭,為什么沒有進入 GoodsDetailViewController ,卻就被釋放掉了?


一辐棒、覺的可能是 TabBarController 那出問題了

因為畢竟此種情況病曾,只有重復點擊 tabbarItem 才出現(xiàn)的,于是對里面進行檢查漾根,發(fā)現(xiàn)就算我將里面完全復原成最基本的情況泰涂,也還是出現(xiàn)這種情況。辐怕。逼蒙。

二、想著是否有 TabBarController 的Category 或者說其他的 分類有影響

在項目中轉了一圈寄疏,發(fā)現(xiàn)是木有的是牢。。陕截。

三妖泄、試著用 Present 換換 Push ,看看會有什么效果
  [self.viewController presentViewController:goodsDetailVC animated:YES completion:nil];

發(fā)現(xiàn)是可以的艘策,然后我就在想是不是和 navigationController 有關呢蹈胡? 然后就發(fā)現(xiàn)類似其他的 Push 都不可以進入...

然后這個問題就擴大了,凡是在 tabBar 第一個頁面中朋蔫,重復點擊選中的 tabBarItem 后罚渐,push 相關的頁面都是失效的...

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated

viewController 都會被釋放掉...

之后對該方法的攔截全部都看一遍,發(fā)現(xiàn)寫的沒問題啊驯妄,而且這個是在點擊之后才壞的荷并,本來這個方法點擊時有效的,而且在不同 tabBarItem 可以同時呈現(xiàn)兩種不同的情況青扔,例如在 home 中雙擊 home tabBarItem 后源织,該方法失效翩伪;而在Categories tabBarItem 沒有重復點擊卻是好的,只有重復點擊后才失效谈息,顯示進入的 viewController 已經釋放了...

四缘屹、找到源點

經過大半天后,有小伙伴在項目中 UINavigationController 的分類中發(fā)現(xiàn)了這個方法...

+ (void)load {
    method_exchangeImplementations(
                class_getInstanceMethod(self, @selector(pushViewController:animated:)), 
                class_getInstanceMethod(self, @selector(safePushViewController:animated:))
    );
}
- (void)safePushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    self.delegate = self;
    //-- If we are already pushing a view controller, we dont push another one.
    if (self.isViewTransitionInProgress == NO) {
        //-- This is not a recursion, due to method swizzling the call below calls the original  method.
        [self safePushViewController:viewController animated:animated];
        if (animated) {
            self.viewTransitionInProgress = YES;
        }
    }
}
@interface UINavigationController () <UINavigationControllerDelegate>

@property (readwrite,getter = isViewTransitionInProgress) BOOL viewTransitionInProgress;

@end

@implementation UINavigationController (Consistent)

- (void)setViewTransitionInProgress:(BOOL)property {
    NSNumber *number = [NSNumber numberWithBool:property];
    objc_setAssociatedObject(self, ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN);
}

- (BOOL)isViewTransitionInProgress {
    NSNumber *number = objc_getAssociatedObject(self, ObjectTagKey);
    return [number boolValue];
}

所以此時再回過頭來看侠仇,就是重復點擊了 tabbarItem 導致 self.isViewTransitionInProgress 變?yōu)閅ES轻姿,而無法繼續(xù)執(zhí)行該方法,從而導致不能 Push 過去逻炊。


重復點擊選中的 tabBarItem 到底為什么會讓該分類中的私有屬性變化呢互亮?

通過日志顯示,第一次點擊 tabbarItem 會被 viewTransitionInProgress 默認設置成 NO余素,重復點擊后 會直接導致 viewTransitionInProgress getter 方法 和 setter 方法被執(zhí)行豹休,其中 setter 方法設置 成 YES。從而下次點擊pushViewController:animated:的時候桨吊,交換了方法威根,self.isViewTransitionInProgress == YES 就不能進入 [self safePushViewController:viewController animated:animated]; 該方法,從而導致不能被執(zhí)行屏积。

PS1: 此處 其中 setter 方法設置 成 YES 是因為該分類中的另一個方法:

- (NSArray *)safePopToRootViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToRootViewControllerAnimated:animated];
}

PS2: 注意上面那個屬性可以得出 readwrite, 默認讀寫的;
getter = isViewTransitionInProgress 修改了 getter 的方法磅甩。

解決

  • 1炊林、注釋剛才那個setter 重新設置成YES 的方法:
//    if (animated) {
//        self.viewTransitionInProgress = YES;
//    }

個人認為在 rootViewController,viewTransitionInProgress 應該默認是NO卷要,暫時無發(fā)現(xiàn)有什么問題渣聚。

  • 2、另外就是直接干掉這個分類僧叉,因為實際上在該項目中它這個分類用處不是很大奕枝,是起預防的,所以也可以直接不用它瓶堕。

總的說來隘道,下次遇到類似的問題,可以到分類中看看郎笆,有沒有用到 Runtime 的方法谭梗。
另外用Runtime 系列方法也一定要謹慎!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末宛蚓,一起剝皮案震驚了整個濱河市激捏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凄吏,老刑警劉巖远舅,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闰蛔,死亡現(xiàn)場離奇詭異,居然都是意外死亡图柏,警方通過查閱死者的電腦和手機序六,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爆办,“玉大人难咕,你說我怎么就攤上這事【嗔荆” “怎么了余佃?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跨算。 經常有香客問我爆土,道長,這世上最難降的妖魔是什么诸蚕? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任步势,我火速辦了婚禮,結果婚禮上背犯,老公的妹妹穿的比我還像新娘坏瘩。我一直安慰自己,他們只是感情好漠魏,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布倔矾。 她就那樣靜靜地躺著,像睡著了一般柱锹。 火紅的嫁衣襯著肌膚如雪哪自。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天禁熏,我揣著相機與錄音壤巷,去河邊找鬼。 笑死瞧毙,一個胖子當著我的面吹牛胧华,可吹牛的內容都是我干的。 我是一名探鬼主播宙彪,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼撑柔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了您访?” 一聲冷哼從身側響起铅忿,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灵汪,沒想到半個月后檀训,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柑潦,經...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年峻凫,在試婚紗的時候發(fā)現(xiàn)自己被綠了渗鬼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡荧琼,死狀恐怖譬胎,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情命锄,我是刑警寧澤堰乔,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站脐恩,受9級特大地震影響镐侯,放射性物質發(fā)生泄漏。R本人自食惡果不足惜驶冒,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一苟翻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧骗污,春花似錦崇猫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贴谎,卻和暖如春汞扎,著一層夾襖步出監(jiān)牢的瞬間季稳,已是汗流浹背擅这。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留景鼠,地道東北人仲翎。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像铛漓,于是被迫代替她去往敵國和親溯香。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內容