Objective-C:为什么在使用参数调用 objc_msgSend 时出现 EXC_BAD_ACCESS 异常?

Objective-C: Why do I get an EXC_BAD_ACCESS exception when calling objc_msgSend with a parameter?

我在 Sprite Kit / iOS 7.0 中处理自己的按钮 class 时遇到了一些问题。一旦我尝试使用 "objc_msgSend" 回调方法,我就会收到以下错误:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x8)

这是我的按钮 class,其中 "identifier" 返回给调用者:

// Header File *.h
@property (nonatomic, readwrite, strong) NSString* identifier;
@property (nonatomic, readonly, weak) id targetTouchUpInside;
@property (nonatomic, readonly) SEL actionTouchUpInside;

// Implementation File *.m
// ... this code is in the initializer method
NSMutableString *identifier = [[NSMutableString alloc]init];
[identifier appendFormat:@"%d:%d", menuId, itemId];
[self setIdentifier:[identifier copy]];

// ... this code is called to inform the observer about an event
objc_msgSend(_targetTouchUpInside, _actionTouchUpInside, _identifier);

这是 Button 在检测到触摸时立即调用的回调方法。这是抛出 EXC_BAD_ACCESS 异常的地方。 "identifier" 是 "nil",但仅在 iPad Air 上,有趣的是它在 iPhone 4S 上运行良好。

// ... this is the callback method in the object that instantiates the button object
- (void)itemTouchInside:(NSString*)identifier {
    NSLog(@"ID CALLED: %@", identifier);
}

我观察到当我调用 "objc_msgSend" 时它也适用于 iPad ...

但我需要动态定义 _identifier,如上面的代码片段所示。

知道为什么这适用于 iPhone 而不是 iPad 吗?

为触摸事件创建协议,然后进行类型检查。你所有的问题都会消失。或者使用积木。现在目标和选择器可能指向错误类型的对象 类.

我建议您将 objc_msgSend 的用法替换为以下内容:

[self.targetTouchUpInside performSelector:self.actionTouchUpInside withObject:self.identifier];

还要注意属性的使用。你有属性,用它们。

正如其他人提到的,最好用 copy 定义 identifier 属性 而不是 strong。消除了一些可能(且难以发现)的错误。