美文网首页iOS开发资料收集区
NSInvocation使用时遇到的问题记录

NSInvocation使用时遇到的问题记录

作者: 奴良 | 来源:发表于2018-12-03 17:02 被阅读12次

前言

至于为什么要使用NSInvocation,由于在项目中Debug模式下加一个FLEX的开关,但是在打包上架时候总会打包失败,报一个找不到<FLEX/FLEX.h>头文件的错误,所以就选择了这种方案

小型目录

  • 关于methodSignatureForSelectorinstanceMethodSignatureForSelector的调用解释
  • 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有两种方法
      1. [class instanceMethodSignatureForSelector:sel]
      1. [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

相关文章

网友评论

    本文标题:NSInvocation使用时遇到的问题记录

    本文链接:https://www.haomeiwen.com/subject/fxzycqtx.html