標籤:rac efi fork https define release tco rip tail
??接上篇《 iOS中的crash防護(一)unrecognized selector sent to instance》 我們攻克了找不到方法實現的crash,這一篇我這裡主要分析一下在KVC常見的crash。以及防護措施。
[object setValue:nil forKey:key]
?? value為nil。key不為nil的時候會調用-(void)setNilValueForKey:(NSString *)key這種方法,我這裡對這種方法進行重寫,代碼例如以下:
-(void)setNilValueForKey:(NSString *)key{ NSString *crashMessages = [NSString stringWithFormat:@"JKCrashProtect:‘NSInvalidArgumentException‘, reason: ‘[%@ %p setNilValueForKey]: could not set nil as the value for the key %@.‘",NSStringFromClass([self class]),self,key]; [[JKCrashProtect new] JKCrashProtectCollectCrashMessages:crashMessages];}
測試代碼:
NSObject *object = [NSObject new]; [object setValue:nil forKey:@"name"];
執行結果例如以下:
2017-05-04 19:14:14.073 JKCrashProtect_Example[28537:4028815] demo JKCrashProtect:‘NSUnknownKeyException‘, reason: ‘[NSObject 0x600000003b30 setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key: name,value:(null)‘
大家能夠看到程式不再產生crash,並且將crash列印資訊 出來方便我們定位crash。
非對象屬性value為nil產生的crash
執行個體代碼例如以下:
@interface Person : NSObject@property (nonatomic,copy)NSString *name;@property (nonatomic,assign)NSInteger age;@end
測試代碼:
Person *jack = [Person new]; [jack setValue:nil forKey:@"age"];
假設我們不進行crash防護的話,上面的這段測試代碼就會產生crash,可是進行防護後。執行結果例如以下:
2017-05-04 21:19:52.496 JKCrashProtect_Example[29792:4065383] demo JKCrashProtect:‘NSInvalidArgumentException‘, reason: ‘[Person 0x608000225560 setNilValueForKey]: could not set nil as the value for the key age.‘
程式並沒有crash,並且crash資訊也被列印了出來,方便我們定位。
key不是object的屬性產生的crash
??假設key不是object的屬性的話,我們進行KVC賦值操作的話,也是會產生crash的。
測試代碼例如以下:
NSObject *object = [NSObject new]; [object setValue:@"abc" forKey:@"123"];
執行結果例如以下:
2017-05-04 21:26:21.357 JKCrashProtect_Example[29942:4071385] demo JKCrashProtect:‘NSUnknownKeyException‘, reason: ‘[NSObject 0x600000203180 setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key: 123,value:abc‘
程式相同沒有崩潰。並且將crash列印資訊了出來,方便我們定位。
[object setValue:value forKey:nil]產生的crash
?? 當key為nil的時候程式會產生crash。當然了這裡能夠通過method swizzle進行處理,可是這違背了,JKCrashProtect建立的初衷:僅僅在crash產生的時候,進行相關的處理,沒有crash的時候。程式正常執行。儘可能少的產生效能損耗。這個在靜態時,編譯器會有警告,一般這個crash產生在動態傳入key時未做非空處理,我這邊臨時沒有好的解決方式。假設大家有的話,歡迎大家留言一塊討論哦。
[object setValue:value forKeyPath:keyPath];
?? 假設keyPath不對,這個時候程式也會產生crash,我這邊進行crash防護後。測試代碼例如以下:
@interface Country : NSObject@property (nonatomic,copy)NSString *name;@end@interface Person : NSObject@property (nonatomic,copy)NSString *name;@property (nonatomic,assign)NSInteger age;@property (nonatomic,strong)Country *country;@end
Country *country = [Country new]; jack.country =country; [jack setValue:@"111" forKeyPath:@"abc.name"];
這裡keyPath我隨便寫了一個。執行結果例如以下:
2017-05-04 23:30:20.580 JKCrashProtect_Example[30774:4107964] demo JKCrashProtect:‘Terminating app due to uncaught exception ‘NSUnknownKeyException‘, reason: ‘[Person 0x6000004280c0 valueForUndefinedKey:]: this class is not key value coding-compliant for the key: abc
程式並沒有crash。並且crash資訊也被列印了出來,方便我們定位。
今天要說的就這些了。歡迎大家持續關注哦。
demo地址
cocoaPod:
pod "JKCrashProtect"
iOS中的crash防護(二)KVC造成的crash