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 ...
随机推荐
- 新建MMS草稿保存后,再进入草稿修改收件人,退出到会话界面,会显示两条草稿
分析原因:新建彩信草稿,保存后,再打开草稿,修改收件人,再保存会产生新的threadId, 而之前保存的草稿theadId还存在,导致此问题. (必现. 解决方法:将原来的Thread_id和新的收件 ...
- 《深入理解Spark:核心思想与源码分析》一书正式出版上市
自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...
- CAST和CONVERT差别与联系
CAST和CONVERT:都是将一种数据类型转换成为另一种数据类型. CAST: CAST ( expression AS data_type [ ( length ) ] ) EG: )) ) as ...
- jQuery in action 3rd - Selecting elements
jQuery(selector) / $(selector) selector 选择器有多种形式,下面是 #ID,.class,element jQuery 支持的 CSS 层级关系选择器 jQuer ...
- C语言误区
int date[10] ; //定义一个字长10的数组,从date[0]....date[9] static char c ; //静态变量(有静态外部变量和静态局部变量),静态外部变量 ...
- 第一个Struts1步骤
一.前端 :登陆页面 index.jsp <%@ page language="java" import="java.util.*" pageEncodi ...
- Java 第一课
怎么去学习java: 1,课前预习,加深对课上学习的吸收! 2,课后预习,让我们能够对所学内容的掌握! 3.通过画流程图,锻炼逻辑思维能力,学会从程序员的角度去看到问题,摒弃以前的惯性的思维方式!
- delphi 处理图片(剪切,压缩)
剪切bmp:效果为指定的rect大小,若图片比rect小,则会放大. 都要uses Vcl.Imaging.jpeg; 需要注意的是FMX里也需要jpeg的支持,虽然没引用编译器不会报错,但用到jpg ...
- 让Sqlite脱离VC++ Runtime独立运行
前段时间在开发OrayTalk(傲瑞通)的聊天记录模块时用到了Sqlite,这是我第一次接触和使用Sqlite,总体感觉还是非常不错的.这里把我使用Sqlite的经验跟大家分享一下. 一.关于Sqli ...
- Ora-01536:超出了表空间users的空间限量(转)
Ora-01536:超出了表空间users的空间限量(转) 正在开会,同事跑过来说数据库有问题,通讯程序不能入库,赶快获取一条insert into a values()语句后在toad工具中手动插入 ...