今天测试在测试的时候遇到个场景发生了Crash
iOS原生跳转到我们自身小程序,然后小程序点击了一个按钮,然后关闭小程序接着调用原生的一个push到一个ViewController加载webView
iOS原生工作台 -> 小程序SDK -> 小程序组件(点击一个按钮) -> 关闭小程序 -> 回到原生 -> 原生跳转到新的ViewController加载WebView
但就是关闭小程序到原生这个过程,是先popViewControllerAnimated的,然后紧接着传回调,然后回到原生工作台,跳转到对应的组件,但是在这个过程当中,崩溃堆栈可以看到
首先崩溃的原因是是在dealloc当中写了,这个是小问题,后面改成_webView就好了,但还是有问题
-(void)dealloc{
[self.webView removeObserver:self forKeyPath:@"123"];
[self.webView removeObserver:self forKeyPath:@"321"];
[self.webView removeObserver:self forKeyPath:@"213"];
}
而小程序SDK当中关闭小程序写的代码为
[self.navigationController popViewControllerAnimated:YES];
...... 抛出回调是否退出成功
来到原生跳转则是直接创建了一个ViewController
打断点可以确认的是先走了小程序SDK关闭,然后才来到跳转ViewController,那为什么上面堆栈信息先走dealloc,才走webView呢
反复看了SDK的代码,发现就只有popViewControllerAnimated,然后猜测这句代码可能不是在主线程执行,把代码都包在了主线程块里面,还是一样Crash,但是一旦去掉就是好的,开始查询popViewControllerAnimated的问题
然后自己写了一个Demo来测试,复现上述结果
打印结果为:
2021-12-21 18:17:58.203173+0800 test[34801:253086] 213
2021-12-21 18:17:58.204249+0800 test[34801:253086] 我执行完popViewControllerAnimated了
2021-12-21 18:17:58.204348+0800 test[34801:253086] block执行了
2021-12-21 18:17:58.714026+0800 test[34801:253086] 我执行了delloc
搞了一系列骚操作,都能正常跳转,在demo里面复现不出来这个问题,开始看popViewControllerAnimated有没有被重写或者啥的,果然发现popViewControllerAnimated是被method_exchangeImplementations了的
- (UIViewController *)safePopViewControllerAnimated:(BOOL)animated {
if (self.viewTransitionInProgress) return nil;
if (animated) {
self.viewTransitionInProgress = YES;
}
UIViewController *viewController = [self safePopViewControllerAnimated:animated];
if (viewController == nil) {
self.viewTransitionInProgress = NO;
}
return viewController;
}
现在问题就很清晰了,是因为防止在转场的过程中跳转,加的保护,而在这边我们跳转从小程序SDK关闭pop然后再push,push并没有成功,VC创建后在作用域结束后就直接dealloc了,所以才会走到dealloc,然后dealloc又去持有了webView,所以造成了这样的问题。