前言
至于为什么要使用NSInvocation
,由于在项目中Debug
模式下加一个FLEX
的开关,但是在打包上架时候总会打包失败,报一个找不到<FLEX/FLEX.h>
头文件的错误,所以就选择了这种方案
小型目录
- 关于
methodSignatureForSelector
及instanceMethodSignatureForSelector
的调用解释 -
invoke
类方法及实例方法 - 执行
invoke
后造成memory leak
然后报错(EXC_BAD_ACCESS
)crash的解决方案
下面代码均以
FLEX
来举例,包括获取当前显示状态,及设置其显示隐藏
获取NSMethodSignature
对FLEX
进行操作,首先要获取其单例
- (id)getFlexManager
{
Class flex = NSClassFromString(@"FLEXManager");
SEL sharedManagerSEL = NSSelectorFromString(@"sharedManager");
__autoreleasing id manager = nil;
NSMethodSignature *signature = [flex methodSignatureForSelector:sharedManagerSEL];
if (signature) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
// sharedManager 是类方法,这里的target设置类本身即可
invocation.target = flex;
invocation.selector = sharedManagerSEL;
[invocation invoke];
// 获取其返回值
[invocation getReturnValue:&manager];
}
return manager;
}
获取显示状态
- (BOOL)getFlexIsHidden
{
id manager = [self getFlexManager];
if (!manager) return YES;
BOOL isHidden = NO;
SEL isHiddenSEL = NSSelectorFromString(@"isHidden");
NSMethodSignature *signature = [manager methodSignatureForSelector:isHiddenSEL];
if (manager && signature) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = manager;
invocation.selector = isHiddenSEL;
[invocation invoke];
[invocation getReturnValue:&isHidden];
}
return isHidden;
}
小结
- 当方法为类方法是
invocation.target
为类本身,实例方法时为其实例对象 - 获取类方法的
NSMethodSignature
需要用其类名调用methodSignatureForSelector
- 获取实例方法的
NSMethodSignature
有两种方法[class instanceMethodSignatureForSelector:sel]
[instance methodSignatureForSelector:sel]
设置FLEX
显示及隐藏
- (void)setFlexManagerIsShow:(BOOL)show
{
id manager = [self getFlexManager];
if (!manager) return;
SEL sel = show ? NSSelectorFromString(@"showExplorer") : NSSelectorFromString(@"hideExplorer")
NSMethodSignature *signature = [manager methodSignatureForSelector:sel];
if (signature) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = manager;
invocation.selector = sel;
[invocation invoke];
}
}
关于内存泄漏导致的crash
可以翻上去看一下getFlexManager
方法,在声明manager
时候前面添加了一个__autoreleasing
,如果不添加的话,便会造成crash
参考链接: NSInvocation returns value but makes app crash with EXC_BAD_ACCESS
网友评论