##前言 最近项目有几个因为NSDictionary的value或者key是nil导致崩溃的bug,虽然不多,但是检查起来却有些麻烦,为了省事,直接把系统的几个方法替换成了自己的方法。 举个栗子:NSMutableDictionary:
Class class = NSClassFromString(@"__NSDictionaryM");
[class mhs_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(gl_setObject:forKey:)];
[class mhs_swizzleMethod:@selector(setObject:forKeyedSubscript:) withMethod:@selector(gl_setObject:forKeyedSubscript:)];
复制代码
实现:
- (void)mhs_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
if (!aKey) {//没有key直接return掉
return;
}
if (!anObject) {//没有value则赋一个NSNull对象
anObject = [NSNull null];
}
[self mhs_setObject:anObject forKey:aKey];
}
- (void)mhs_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
if (!key) {
return;
}
if (!obj) {//打印一下,用于测试
#if defined(DEBUG)||defined(_DEBUG)
NSLog(@"有空值setObject:forKeyedSubscript: key=%@",key);
#endif
obj = [NSNull null];
}
[self mhs_setObject:obj forKeyedSubscript:key];
}
复制代码
结果发现,会打印很多,诸如:
##继续 更新版本后,突然涌现大量崩溃,不知为何,友盟统计都是这种崩溃日志: Application received signal SIGSEGV Application received signal SIGBUS SIGSEGV和SIGBUS一般是因为访问已被释放的内存或者调用不存在的方法导致的,但是没有具体信息。回想了一下更新版本我所做的修改,一个是swizzleMethod,一个是应用里数据库的一些优化,想来想去,也就只有这里可能有问题。而且基本上崩溃都是应用进入后台再唤醒进入前台后发生。(重要信息)
##但是
我大量测试应用发生崩溃的条件发现崩溃看起来好像跟swizzleMethod没有关系。
##结论 swizzle系统方法不可滥用,首先系统如何实现没有开源谁都不知道,任意更改谁也不敢保证一定安全,应该在平时细心注意,避免出现低级错误而非投机取巧运用黑魔法。 虽然我不知道极光SDK经历了什么,我也不知道为什么会导致崩溃,但是事实确实如此,幸亏崩溃发生条件比较明显,那就是从后台进入前台,要不然我真会浪费更多的精力在这上面。