runtime MethodSwizzle 实践之 奇怪crash : [UIKeyboardLayoutStar release]: message sent to deallocated instance
情景: 使用MethodSwizzle 实现对数组、字典 等系统方法的安全校验。显然能达到预期效果,但实际发现当
键盘显示的情况下 home app 进入后台,再单击app 图标 切换回前台时 发生crash :
[UIKeyboardLayoutStar release]: message sent to deallocated instance
UIKeyboardLayoutStar 是键盘上的布局的视图吧,
整个工程都在ARC下 构建,很奇怪,而且必须。
信息:
其中都有提到DurexKit 原理都是一样的,上面提到原因是替换了 NSArray的objectAtIndex: 方法,
不过在我的项目原因是替换了NSMutableArray 的objectAtIndex:( NSMutableArray和 NSArray 的objectAtIndex:都有替换,单独替换 NSArray 的objectAtIndex:方法则不会引起crash)
解决方案:给 添加非ARC 支持,并改写实现
有提到:。。貌似 arc 有时也不一定可靠。
----------------------2015.3.23-----更新--0.0--继续填坑啊----------------------------------
话说使用 语法糖初始化 数组和 字典 真的好方便。。。@{....} @[...] 但是很容易埋雷。。大多数里面存的都是变量 在代码里。so , 也需要校验 。
最初使用 MethodSwizzle 很嗨皮啊,首先涉及可变参数在替换的方法里 试图使用NSInvocation 来解决 传递多个参数的问题,最后 莫名crash 。。你可以试试。
再说说数组和字典里的类簇(工厂模式):
http://blog.sunnyxx.com/2014/12/18/class-cluster/
后来发现如果你用语法糖 初始化数组 crash 信息如下:
'*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from xx
解决方案使用静态方法 + objc_msgSend 来实现:
#import <objc/message.h> #define CurrentClass objc_getClass("__NSArrayI") static id array_safe_initWithObjects(id self, SEL _cmd, const id* objects,unsigned int count){
id orignialResult = nil;
@try {
orignialResult = objc_msgSend(self, @selector(array_safe_initWithObjects:count:),objects,count);
}
@catch (NSException *exception) {
DDLogDebug(@"=__NSPlaceholderArray===BUSTED!");
}
return orignialResult ;
} @implementation NSArray (SafeCheck) +(void)load{
//添加
[CurrentClass swizzleInstanceSelector:@selector(objectAtIndex:) withNewSelector:@selector(safeObjectsAtIndex:)]; [objc_getClass("__NSPlaceholderArray") swizzleSelector: @selector(initWithObjects:count:) withNewSelector:@selector(array_safe_initWithObjects:count:) andNewIMP:(IMP)&array_safe_initWithObjects];
}
+ (void) swizzleSelector:(SEL)originalSelector
withNewSelector:(SEL)newSelector
andNewIMP:(IMP)imp{ Method originMethod = class_getInstanceMethod(self, originalSelector);
const char * methodEncodeType = method_getTypeEncoding(originMethod);
BOOL methodAdded = class_addMethod(self, newSelector, imp, methodEncodeType); if (methodAdded) {
Method newMethod = class_getInstanceMethod(self,newSelector);
method_exchangeImplementations(newMethod, originMethod);
}else{
DDLogDebug(@"=====faile=");
}
}
在运行时中会维护 selector 和 IMP 对应关系表。
同理字典也一样呢可以使用这种方法 添加语法糖校验。
#import <objc/message.h> static id dic_safe_initWithObjects(id self, SEL _cmd, const id* objects, const id* keys, unsigned int count) { id orignialResult = nil; @try {
orignialResult = objc_msgSend(self, @selector(dic_safe_initWithObjects:forKeys:count:), objects, keys, count);
}
@catch (NSException *exception) {
DDLogDebug(@"__NSPlaceholderDictionary===BUSTED!");
} return orignialResult;
} @implementation NSDictionary (SafeCheck)
+(void)load{
[objc_getClass("__NSPlaceholderDictionary") swizzleSelector:@selector(initWithObjects:forKeys:count:) withNewSelector:@selector(dic_safe_initWithObjects:forKeys:count:) andNewIMP:(IMP)&dic_safe_initWithObjects];
}
runtime MethodSwizzle 实践之 奇怪crash : [UIKeyboardLayoutStar release]: message sent to deallocated instance的更多相关文章
- -[UIKeyboardLayoutStar release]: message sent to deallocated instance 0x7fbe49120000
__NSArrayM objectAtIndex: 取消swizzle 只有debug的时候会报错,发布的时候是好的,所以可以不用改
- -[UIKeyboardLayoutStar release]: message sent to deallocated instance
网上大家都说是因为替换了系统的objextAtIndex方法,但是为了减少应用崩溃的可能,是要进行Hook的,所以不想取消Hook. 解决办法,关掉键盘进入后台. - (void)applicatio ...
- [CALayer release]: message sent to deallocated instance iOS内存过度释放问题
[CALayer release]: message sent to deallocated instance iOS内存过度释放问题 解决方式: 1:先找到过度释放的 内存指针 开启-僵尸模式:xc ...
- [CALayer release]: message sent to deallocated instance
遇到此问题时,查看以下类的dealloc方法中是否有过度释放. 可以在release前先判断以下对象是否还存在. -(void)dealloc { if (!m_tableView) [m_table ...
- runtime MethodSwizzle 实践之扩展 NIAttributedLabel
runtime MethodeSwizzle 提供 简单的方法交换已知类的 Method IMP. Method 可以是 外部可访问的 public 或者 private Method .所谓的属性 ...
- iPhone开发过程中调试多次Release问题 message sent to deallocated
初级:第一步 为程序添加符号断点 malloc_error_break 方法如下. 目标效果:让程序崩溃时跳转到出错到那一行.但是往往达不到这个效果.不行就继续往下看. At times, wh ...
- 【kudu pk parquet】runtime filter实践
已经有好一阵子没有写博文了,今天给大家带来一篇最近一段时间开发相关的文章:在impala和kudu上支持runtime filter. 大家搜索下实践者社区,可以发现前面已经有好几位同学写了这个主题的 ...
- [20180124]奇怪的SQL*Net message from dblink.txt
[20180124]奇怪的SQL*Net message from dblink.txt --//生产系统出现大量的SQL*Net message from dblink事件,自己分析看看. 1.环境 ...
- 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE
<CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...
随机推荐
- text-indent
<div class="top wd"> <div class="con fl "><a href="#"&g ...
- Android照片墙应用实现,再多的图片也不怕崩溃
本文首发于CSDN博客,转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9526203 照片墙这种功能现在应该算是挺常见了,在很多应用 ...
- 对于C++窗口编译一闪而过的解决方法 (DEV CPP下)
对于C++窗口编译一闪而过的解决方法 首先来看一个简单的程序(编译环境为 DEV C++.): #include <iostream> int main() { std:: ...
- 3D扫描系统的构建(待处理)
1. http://www.zhihu.com/question/32143353 是否可以 DIY 一个 3D 扫描仪或者开源 3D 扫描项目? 详细的原理介绍 2. http://www.csks ...
- poj 3635/hdu 1676 Full Tank? 车辆加油+最短路
http://acm.hdu.edu.cn/showproblem.php?pid=1676 给出一张图,n<=1000,m<=10000. 有一辆车想从图的一个地方到达另外一个地方,每个 ...
- Jquery插件实现点击获取验证码后60秒内禁止重新获取
通过jquery.cookie.js插件可以快速实现“点击获取验证码后60秒内禁止重新获取(防刷新)”的功能 先到官网(http://plugins.jquery.com/cookie/ )下载coo ...
- SQLite数据库在本地可以写,发布到服务器就不能写
用SQLite开发的一个Web Api,提供Json和Jsonp格式的数据,在本地使用vs2012开发并运行时,数据库的读写均正常. 但发布到Windows Server 2008 + IIS 7.5 ...
- 在Mac OS X上用自己编译出的CoreCLR运行.NET程序
当昨天被Mac OS X上无法编译CoreCLR的问题困扰时(详见Mac OS X上尝试编译CoreCLR源代码),后来发现这个难题竟然被神人@kangaroo给解决了,连CoreCLR的微软开发人员 ...
- 容易答错的JS笔试题
1,考察this var length = 10 function fn(){ alert(this.length) } var obj = { length: 5, meth ...
- [MSSQL2005]再看CTE
个人认为CTE最大的做点是可以处理树状存储的数据了 例如类似这样设计的数据表,ID,ParentID这样的设计使用CTE就非常方便,原因就是CTE可以自引用,达到类似递归的效果 那么问题来了,如何使用 ...