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 ...
随机推荐
- 关于Control flow
1.一个package包含一个control flow并且一个或多个data flow. (这个项目叫做 Integration services project,提供了三种不同类型的control ...
- ansible 2.2的源码编译安装
ansible代码下载地址:http://releases.ansible.com/ansible/ # git clone git://github.com/ansible/ansible.git ...
- ubuntu 14.04 unity 管理工具 unity-tweak-tool
安装方式: sudo apt-get update sudo apt-get install unity-tweak-tool 用于更改字体,修改状态,disable 亚马逊的搜索等 功能.很好用
- React与ES6(三)ES6类和方法绑定
React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...
- Digit Root ---- 余九定理
题目:hdu1013, hdu1163, 51nod1116. or dr(n) = (n-1)%9+1. 其中,n-1是为了将结果0-8匹配到1-9. Reference: [1] https:// ...
- VS2013_QT255开发相关技巧理解心得
1. 在VS2013中打开QTCreater新建的项目 (1)通过双击.ui 打开QT的设计器,然后修改. (2)通过QT设计器,新建ui文件,放在VSQT的工程中 但是需要对此xxx.ui文件,进行 ...
- 撰写合格的REST API
原文 : http://mp.weixin.qq.com/s?__biz=MzA3NDM0ODQwMw==&mid=208060670&idx=1&sn=ce67b889698 ...
- 初识ASP.NET 5中的Sake与KoreBuild
从github上签出基于ASP.NET 5的MVC 6的源代码进行编译,发现有2个编译命令: build.cmd是针对Windows的编译命令,build.sh是针对Mac/Linux的编译命令,这本 ...
- 每周一道数据结构(四)A*算法&博弈树α-β剪枝
A*算法/博弈树 前阵子考试学了A*算法.博弈树和回溯,自己真是愚蠢至极,根本没就搞明白这些,所以对于这些算法问道的话就不能说清楚,也记不住,所以才有了这篇笔记.在这里感谢面试我的那位工程师~~ A* ...
- 基于D3JS绘制中国地图
仿照D3JS官网上的美国地图制作了一个中国版的地图. D3JS官网上的版本: http://bl.ocks.org/NPashaP/a74faf20b492ad377312 中国版的地图效果: 如要制 ...