得物 H5容器 野指针疑难问题排查 & 解决

文章详细描述了一起由于WKWebView在处理横向滚动内容时引发的内存野指针崩溃问题,分析了问题出现的场景、原因以及不完美的解决方案。通过阅读WebKit源码,找到了问题根源在于WKChildScrollView的delegate,在页面生命周期的特定阶段设置为空以避免崩溃。同时,文章提到了Objective-C中野指针问题的定位方法,如Zombie监控和Coredump分析,并介绍了苹果WebKit内部对此问题的修复。最后,文章分享了线下技术沙龙活动信息。

1背景

得物 iOS 4.9.x 版本 上线后,一些带有横向滚动内容的h5页面,有一个webkit 相关crash增加较快。通过Crash堆栈判断是UIScrollview执行滚动动画过程中内存野指针导致的崩溃。

2前期排查

通过页面浏览日志,发现发生崩溃时所在的页面都是在h5 web容器内,且都是在页面的生命周期方法viewDidDisappear方法调用后才发生崩溃,因此推测崩溃是在h5 页面返回时发生的。

刚好交易的同事复现了崩溃证实了我们的推测。因此可以基本确定:崩溃的原因是页面退出后,页面内存被释放,但是滚动动画继续执行,这时崩溃堆栈中scrollview的delegate没有置空,系统继续执行delegate的相关方法,访问了已经释放的对象的内存(野指针问题)。

同时发生crash h5 页面都存在一个特点,就是页面内存在可以左右横滑的tab视图。

操作手势侧滑存在体验问题,左右横滑的tab视图也会跟着滚动(见下面视频)。关联bugly用户行为日志,判断这个体验问题是和本文中的crash有相关性的。

点击查看公众号完整视频

3不完美的解决方案

经过上面的分析,修复思路是在h5页面手势侧滑返回时,将h5容器页面内tab的横滑手势禁掉(同时需要在 h5 web容器的viewWillAppear方法里将手势再打开,因为手势侧滑是可以取消在返回页面)。

具体代码如下(这样在操作页面侧滑返回时,页面的手势被禁掉,不会再滚动):

@objc dynamic func webViewCanScroll(enable:Bool) {
        let contentView = self.webView.scrollView.subviews.first { view in
            if let className = object_getClass(view), NSStringFromClass(className) == "WKContentView" {
                return true
            }
            return false
        }
        let webTouchEventsGestureRecognizer = contentView?.gestureRecognizers?.first(where: { gesture in
            if let className = object_getClass(gesture), NSStringFromClass(className) == "UIWebTouchEventsGestureRecognizer" {
                return true
            }
            return false
        })
        webTouchEventsGestureRecognizer?.isEnabled = enable
    }

经过测试,h5 web容器侧滑时出现的tab页面左右滚动的体验问题确实被解决。这样既可以解决体验问题,又可以解决侧滑离开页面导致的崩溃问题,但是这样并没有定位crash的根因。修复代码上线后,crash量确实下降,但是每天还是有一些crash出现,且收到了个别页面极端操作下偶现卡住的问题反馈。因此需要继续排查crash根因,将crash根本解决掉。

继续看文章开始的crash堆栈,通过Crash堆栈判断崩溃原因是UIScrollview执行滚动动画过程中回调代理方法(见上图)时访问被释放的内存。常规解决思路是在退出页面后,在页面生命周期的dealloc方法中,将UIScrollview的delegate置空即可。WKWebView确实有一个scrollVIew属性,我们在很早的版本就将其delegate属性置空,但是崩溃没有解决。

deinit {
         scrollView.delegate = nil
         
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值