objective-c – 为什么objc_msgSend导致EXC_BAD_ACCESS?

我正在创建一个类,给定一个对象目标,一个要监视的选择器,displayTitle将以这种格式输出一个字符串:@“displayTitle:object.selector”.然后它通过KVO注册自己,这样只要object.selector的值发生变化,它就可以通知视图控制器更新视图.我使用它作为一种抽象和可重用的方式向用户显示对象的各种属性的描述.

当我尝试获取object.selector的值时,我无法执行[object performSelector:selector]因为LLVM gives errors when you use performSelector with a dynamic selector.
所以,我完全按照this answer的建议做了:我使用了objc_msgSend(对象,选择器).

- (instancetype)initWithSelector:(SEL)selector onObject:(NSObject*)object displayTitle:(Nsstring*)displayTitle {
    self = [super init];

    if (self) {
        id value;

        if ([object respondsToSelector:selector) {
            // Used objc_msgSend instead of performSelector to suppress a LLVM warning which was caused by using a dynamic selector.
            value = objc_msgSend(object,selector);
        } else {
            return nil;
        }

        [self setItemDescription:[Nsstring stringWithFormat:@"%@: %@",displayTitle,value]];
    }

    return self;
}

我得到了一个EXC_BAD_ACCESS!

正如您在屏幕截图中看到的那样,我确保了这一点
做[对象选择器]工作.

发生了什么,我该如何解决

解决方法

您将objc_msgSend调用的结果分配给类型为id的变量,以便ARC启动并尝试保留结果对象(崩溃在objc_retain中,因为您可以在左侧的堆栈中看到).但是,结果不是对象而是值为8的整数,objc_retain将其作为指针.但是没有这么低的有效指针,所以你得到了EXC_BAD_ACCESS.

只需将值的类型更改为NSUInteger(或任何其他非对象类型).但请确保所有潜在的选择器都返回相同类型的数据.或者,确保始终返回一个可以由ARC保留的对象(或零).

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...