非主线程刷UI
hook UIView的下列三个方法:
- setNeedsLayout
- setNeedsDisplay
- setNeedsDisplayInRect
判断当前是否在主线程,如果不在则通过dispatch_async(dispatch_get_main_queue(), ^{ //调用原本方法 });,此方法暂时不能做到完全覆盖
访问野指针
- hook NSObject 的allocWithZone方法,判断当前对象是否需要加入野指针防护。因为很多系统类释放频繁,且发生野指针的概率较低,过滤可以提高效率
- 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]方法即可