iOS KVO crash 自修复技术实现与原理解析

KVO crash 自修复技术实现与原理解析

前言

【前言】KVO API设计很是不合理,因而有不少的KVO三方库,好比 KVOController 用更优的API来规避这些crash,可是侵入性比较大,必须编码规范来约束全部人都要使用该方式。有没有什么更优雅,无感知的接入方式?html

简介

KVO crash 也是很是常见的 Crash 类型,在探讨 KVO crash 缘由前,咱们先来看一下传统的KVO写发:git

#warning move this to top of .m file
//#define MyKVOContext(A) static void * const A = (void*)&A;
static void * const MyContext = (void*)&MyContext;

#warning move this to viewdidload or init method 
   // KVO注册监听:
   // _A 监听 _B  的 @"keyPath"  属性
   //[self.B  addObserver: self.A forKeyPath:@"keyPath" options:NSKeyValueObservingOptionNew context:MyContext];

- (void)dealloc {
   // KVO反注册
   [_B removeObserver:_A forKeyPath:@"keyPath"];
}

// KVO监听执行 
#warning — please move this method to  the class of _A  
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
   if(context != MyContext) {
       [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
       return;
   }
   if(context == MyContext) {
   //if ([keyPath isEqualToString:@"keyPath"]) {
       id newKey = change[NSKeyValueChangeNewKey];
       BOOL boolValue = [newKey boolValue];
       
   }
}

看到如上的写发,大概咱们就明白了 API 设计不合理的地方:github

B 须要作的工做太多,B可能引发Crash的点也太多:app

B 须要主动移除监听者的时机,不然就crash:this

  • B 在释放变为nil后,hook dealloc时机
  • A 在释放变为nil后 不然报错 Objective-C Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

KVO的被观察者dealloc时仍然注册着KVO致使的crash阿里云

B 不能移除监听者A的时机,不然就crash:编码

  • B没有被A监听
  • B已经移除A的监听。

添加KVO重复添加观察者或重复移除观察者(KVO 注册观察者与移除观察者不匹配)致使的crash。spa

我有几张阿里云幸运券分享给你,用券购买或者升级阿里云相应产品会有特惠惊喜哦!把想要买的产品的幸运券都领走吧!快下手,立刻就要抢光了。设计

采起的措施:code

  • B添加A监听的时候,避免重复添加,移除的时候避免重复移除。
  • B dealloc时及时移除 A
  • A dealloc时,让 B 移除A。
  • 避免重复添加,避免重复移除。

报错信息一览:

2018-01-24 16:08:54.100667+0800 BootingProtection[63487:29487624] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<CYLObserverView: 0x7fb287002fb0; frame = (0 0; 207 368); layer = <CALayer: 0x604000039360>>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.

防crash措施

因而有不少的KVO三方库,好比 KVOController 用更优的API来规避这些crash,可是侵入性比较大,必须编码规范来约束全部人都要使用该方式。有没有什么更优雅,无感知的接入方式?

那即是咱们下面要讲的 KVO crash 防御机制。

相关文章
相关标签/搜索