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 ...
随机推荐
- web兼容性测试
1.前端的兼容性问题 a. 客户端操作系统 -pc电脑 -windows -mac os -Linux -平板 -手机 -智能终端 -响应式布局 借助于css3 b.客户端浏览器 IE firefo ...
- NumberFormat usage
NumberFormat 是所有数值格式的抽象基类. 该类提供了格式化和分析数值的接口. NumberFormat 也提供了确定 哪个语言环境具有数值格式以及它们名字的方法. import java. ...
- 笔记:Hyper-V上Centos 6.5分辨率调整问题解决笔记
最近忙的没有心情写东西,果然博客就这么长草了.今天就稍微写一点点东西吧,反正这问题挺烦的. 背景如下:为准备做redis集群实验,特在笔记本上搭建CentOS6.5的Hyper-V虚拟机. 虚拟机创建 ...
- couchbase作为分布式session容器时的注意事项
在开发MVC程序时,选择了couchbase作为session provider,但在部署的过程当中发现,两台web server负载均衡,只有一台有session,而负载到另外一台web serve ...
- Dynamic CRM 2013学习笔记(二十三)CRM JS智能提示(CRM 相关的方法、属性以及页面字段),及发布前调试
我们知道在CRM的js文件里引用XrmPageTemplate.js后,就可以实现智能提示,但每个js文件都引用太麻烦了,其实可以利用vs的功能让每个js文件自动实现智能提示CRM的js: 另外,我们 ...
- 大熊君说说JS与设计模式之------代理模式Proxy
一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
- Html5文件
HTML5 file api 读取文件MD5码 http://www.zhuwenlong.com/blog/52d6769f93dcae3050000003
- 根据配置文件加载js依赖模块(JavaScript面试题)
面试题目 根据下面的配置文件 module=[ {'name':'jquery','src':'/js/lib/jquery-1.8.3.js'}, {'name':'swfobject','src' ...
- C# 6.0那些事
这两天期中考试没时间去看Connect();直播,挺可惜的,考完后补看了Connect(); 把C#6.0的新东西总结一下. 自动属性初始化 (Initializers for auto-proper ...
- thrift之TTransport层的分帧传输类TFramedTransport
帧传输类就是按照一帧的固定大小来传输数据,所有的写操作首先都是在内存中完成的直到调用了flush操作,然后传输节点在flush操作之后将所有数据根据数据的有效载荷写入数据的长度的二进制块发送出去,允许 ...