假死,就是 APP 没有响应,点击界面任何地方都不会有响应,但是又不会闪退的一种现象。结合网上的一些资料和开发经验总结一下常见的原因:
1.一个透明的视图盖在了整个界面上
在做弹出框,或者遮盖的时候,不要将视图添加到下面的窗口上
[UIApplication sharedApplication].windows.lastObject
最后一个 window 不一定是你当前显示的 window。请看下面的运行结果
[
<UIWindow: 0x13fe11d10; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x1702441d0>; layer = <UIWindowLayer: 0x17003a4a0>>,
<UITextEffectsWindow: 0x13fd7ae00; frame = (0 0; 414 736); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x174222460>>,
<UITextEffectsWindow: 0x141b66f70; frame = (0 0; 414 736); layer = <UIWindowLayer: 0x174a27640>>,
<UIRemoteKeyboardWindow: 0x141b68930; frame = (0 0; 414 736); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x174a27e40>>
]
如果你把视图添加到UIRemoteKeyboardWindow
上,就会出现假死,而你查看视图层级关系是不会发现的。
最好的办法是拿到代理的窗口,把你想要的遮盖加到上面。
UIWindow *window = [UIApplication sharedApplication].delegate.window;
[window addSubview:view];
这只是其中一个例子,仅供参考。
2.死循环
如果不小心写了一个死循环,也会造成假死。可以查看 CPU 使用率。如果达到99%或者100%,说明肯定有死循环了。举个例子,当你写一个懒加载的属性时,不小心写成下面这样,那么就惨了!
- (NSMutableArray *)selectSignal {
if (!_selectSignal) {
_selectSignal = [NSMutableArray array];
}
return self.selectSignal;
}
3.线程问题
当执行了一个比较耗时的方法,而这个方法恰好在主线程,不严重的话就是卡顿,严重一点就出现了假死现象。
还有就是考虑有没有出现死锁,或者是否在子线程中做了 UI 相关的操作。
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"=================4");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"=================5");
});
NSLog(@"=================6");
}
读者朋友如果遇到过其他奇葩原因,欢迎交流。
网友评论