错误使用window引起的内存释放异常而闪退问题
我们经常会碰到app突然crash掉的现象,当出现thread 1:exc_bad_access(code=1,address=0x6565656565)的提示时,这种错误通常是内存管理的问题,一般是访问了已经释放的对象导致的。
现象是:从根页面进入子页面,然后返回根页面就闪退。只有iOS13,iPhone6手机闪退,其它手机没有发现这类闪退。
异常断点跟中闪退在main函数中,进一步跟踪,闪退在objc_release后的0x1b3a6063c <+1936>: ldr x0, [sp, #0x38]。可以看到是显然的内存释放异常。
由于定位不到具体对象,只知道问题肯定出在其它子页面,因为其它页面都正常。
后面只有通过屏蔽代码,然后逐步放开代码,采用试错的方法定位到具体那一行代码。
经过几天测试终于查到具体的导致闪退的代码:
[self.view addSubview:self.window]; [self.window mas_makeConstraints:^(MASConstraintMaker *make) { make.top.leading.trailing.bottom.equalTo(self.view); }];
- (UIWindow *)window{ if (!_window) { _window = [UIWindow new]; _window.backgroundColor = [UIColor colorWithWhite:0 alpha:0.6]; // _window.alpha = 0.8; } return _window; }
分析应该是把window自己直接加在self.view上的,这样用法到只页面无法正常释放而闪退。
进一步分析,原来的作者的目的是:
他希望的不是window,是普通的view,只是这个view要置于页面的最前端,开始是隐藏的,当点击按钮就出现。其实view完全能满足他的需求。要想使它置于最前端有很多种方法,并非一定要用window。其实window主要是用在无法直接获取当前window(不包括通过全局系统变量获取)。如网络请求基础组件。当然还有一种场景是页面过于复杂,存在很多层级关系,并保证有的得页面居于最前面,甚至是多个人同时开发一个超级复杂的页面。为了解藕这种页面会用到多层次window。一般的开发很少涉及多window。最多是获取当前的keywindow(0层window),在上面加入东西,用完要移除。
他的想法是想用window,但是她对window又一知半解,又用到父试图的东西。window要比她想象复杂的多。
使用window的目的就是要实现父试图隔离,像两个页面一样。
其它的她的目的很明确十分明确,就是想实现一个弹窗显示在页面的最前端。没有必要用到window。我的代码最多只出现了三个window,有三层次序关系。多了我也很难管理。有时候window用了是比不用好,但是用不好就是坑。修改后的代码:
- (UIView *)window{ if (!_window) { _window = [UIView new]; _window.backgroundColor = [UIColor colorWithWhite:0 alpha:0.6]; // _window.alpha = 0.8; } return _window; }