两个NSInvocation崩溃引起的反思

简介: 前言最近在使用NSInvocation进行多参数方法调用,结果就崩溃了!signature为nil 和 一直提示找不到方法!!!method signature argument cannot be nil 崩溃信息:*** Terminatin...

前言

最近在使用NSInvocation进行多参数方法调用,结果就崩溃了!signature为nil 和 一直提示找不到方法!!!

method signature argument cannot be nil 崩溃信息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSInvocation _invocationWithMethodSignature:frame:]: method signature argument cannot be nil'
*** First throw call stack:
(0x1831a6d8c  .........)
libc++abi.dylib: terminating with uncaught exception of type NSException

unrecognized selector sent to instance崩溃信息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController openView]: unrecognized selector sent to instance 0x10510b1b0'
*** First throw call stack:
(0x1831a6d8c ......)
libc++abi.dylib: terminating with uncaught exception of type NSException

原始示例代码:

- (void)myInvocation {
    
    SEL myMethod = @selector(sum:parm:parm:);
    //创建一个函数签名,这个签名可以是任意的,但需要注意,签名函数的参数数量要和调用的一致。
    NSMethodSignature * sig  = [[self class] instanceMethodSignatureForSelector:myMethod];
    //通过签名初始化
    NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig];
    //设置target
    [invocatin setTarget:self];
    //设置selecteor
    [invocatin setSelector:myMethod];

    int a=1;
    int b=2;
    int c=3;
    /*
     //index为2 是因为0、1两个参数已经被target和selector占用,其实可以这样设置:
     ViewController * view = self;
     [invocatin setArgument:&view atIndex:0];
     [invocatin setArgument:&myMethod atIndex:1];
     */
    [invocatin setArgument:&a atIndex:2];
    [invocatin setArgument:&b atIndex:3];
    [invocatin setArgument:&c atIndex:4];
    [invocatin retainArguments];
    //我们将c的值设置为返回值
    [invocatin setReturnValue:&c];
    int d;
    //取这个返回值
    [invocatin getReturnValue:&d];
    NSLog(@"%d",d);

    //消息调用
    [invocatin invoke];
    
}

+ (int)sum:(int)a parm:(int)b parm:(int)c{
    NSLog(@"sum: %d:%d:%d",a,b,c);
    return a+b+c;
}

NSInvocation 注意项

一直排查,开始以为是方法名写错了,认真一个一个字检查,没有错哦!!
Way?!

不得而,还是在看看苹果文档!!!


instanceMethodSignatureForSelector:

+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;

Returns an NSMethodSignature object that contains a description of the instance method identified by a given selector.


methodSignatureForSelector:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;

Returns an NSMethodSignature object that contains a description of the method identified by a given selector.


崩溃一 分析:

从苹果文档可以看到,生成NSMethodSignature对象有2个方法,一个是实例方法和一个类方法。

  • 如果SEL是类方法要使用 methodSignatureForSelector:,
  • 如果SEL是实例方法就使用 instanceMethodSignatureForSelector:

所以,把instanceMethodSignatureForSelector: 改为methodSignatureForSelector 就解决啦!

崩溃二 分析:

有了上面的分析,崩溃二是因为 setTarget:使用实例self,而类方法应用使用类,所以修改为[invocatin setTarget:[self class]];,就解决啦!

最终代码:


- (void)myInvocation {
    
    SEL myMethod = @selector(sum:parm:parm:);
    //创建一个函数签名,这个签名可以是任意的,但需要注意,签名函数的参数数量要和调用的一致。
    NSMethodSignature * sig  = [[self class] methodSignatureForSelector:myMethod];
    //通过签名初始化
    NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig];
    //设置target
    [invocatin setTarget:[self class]];
    //设置selecteor
    [invocatin setSelector:myMethod];

    int a=1;
    int b=2;
    int c=3;
    /*
     //index为2 是因为0、1两个参数已经被target和selector占用,其实可以这样设置:
     ViewController * view = self;
     [invocatin setArgument:&view atIndex:0];
     [invocatin setArgument:&myMethod atIndex:1];
     */
    [invocatin setArgument:&a atIndex:2];
    [invocatin setArgument:&b atIndex:3];
    [invocatin setArgument:&c atIndex:4];
    [invocatin retainArguments];
    //我们将c的值设置为返回值
    [invocatin setReturnValue:&c];
    int d;
    //取这个返回值
    [invocatin getReturnValue:&d];
    NSLog(@"%d",d);

    //消息调用
    [invocatin invoke];
    
}

+ (int)sum:(int)a parm:(int)b parm:(int)c{
    NSLog(@"sum: %d:%d:%d",a,b,c);
    return a+b+c;
}

总结

出现这样一个问题,直接说明平时没有关注文档和API实现,当前NSInvocation不常用,但是这次排查也用半天时间,有时候怀疑自己代码时,还是要从根本上找原因——— 从官方文档重新开始!

另外,复制网上的代码是一个危险的动作,不求甚解有时候坑就越深,希望自己以后不懂的知识要使用时,除了工期赶&复制,还要及时补充自己的空白,知其码,并知其然!努力成为一个优秀工程师!严谨!

参考引用


注:本文首发于 iHTCboy's blog,如若转载,请注明来源。

目录
相关文章
|
JavaScript Java 测试技术
基于springboot+vue.js的公交线路查询系统附带文章和源代码设计说明文档ppt
基于springboot+vue.js的公交线路查询系统附带文章和源代码设计说明文档ppt
254 0
|
5天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
5945 8
|
3天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1083 2
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
17天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
3267 10
|
4天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
537 2
|
16天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1828 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
11天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
1257 1

热门文章

最新文章