iOS Crash 防护

非主线程刷UI

hook UIView的下列三个方法:

  • setNeedsLayout
  • setNeedsDisplay
  • setNeedsDisplayInRect

判断当前是否在主线程,如果不在则通过dispatch_async(dispatch_get_main_queue(), ^{ //调用原本方法 });,此方法暂时不能做到完全覆盖

访问野指针

  1. hook NSObject 的allocWithZone方法,判断当前对象是否需要加入野指针防护。因为很多系统类释放频繁,且发生野指针的概率较低,过滤可以提高效率
  2. hook NSObject 的dealloc方法,根据过滤方式,调用objc_destructInstance,释放该实例引用的相关属性,然后调用object_setClass()方法,将实例的isa修改为自定义的一个处理对象

NSArray、NSDictionary、NSString防护

hook真实的类型的对应方法即可,注意要hook真实类型

Unrecognized Selector

根据消息转发流程,选择在哪一个阶段拦截

  • resolveInstanceMethod 需要给类动态添加方法,会增加没必要的开销
  • forwardInvocation 可以动态转发给多个对象,开销较大
  • forwardingTargetForSelector转发给单个对象处理,比较合适

KVO

奔溃发生在以下情况

  • 被观察者dealloc时仍然注册着KVO导致的crash
  • 重复添加观察者或重复移除观察者

解决方案,hook NSObject的addObserver和removeObserver方法,并且给NSObject添加一个关联对象,用来存储观察者和被观察者关系,并将观察者转移给关联对象,关联对象内部判断对应的keyPath是否已经添加了对应的观察者,或者移除了对应的观察者。关联对象内部hook observeValueForKeyPath方法,将实践回调转给原来的观察者。NSObject 还需要hook dealloc方法,用于在被观察者释放的时候,注销观察关系

NSNotification

在对象释放的时候,如果没有移除通知,在iOS9之前会存在奔溃问题。
解决方案,hook NSObject 的dealloc方法,添加[[NSNotificationCenter defaultCenter] removeObserver:self]方法即可

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容