xcode – 使用performSelector执行的方法中的objc_retain中的崩溃

xcode – 使用performSelector执行的方法中的objc_retain中的崩溃,第1张

概述我有这个奇怪的崩溃与ARC自动插入objc_retains在我的代码. 我有以下两个类: @interface MenuItem : NSObject@property (weak, nonatomic) id target;@property (unsafe_unretained, nonatomic) SEL action;@property (strong, nonatomic) id 我有这个奇怪的崩溃与ARC自动插入objc_retains在我的代码.

我有以下两个类:

@interface MenuItem : NSObject@property (weak,nonatomic) ID target;@property (unsafe_unretained,nonatomic) SEL action;@property (strong,nonatomic) ID object;- (instancetype)initWIthTarget:(ID)target action:(SEL)action withObject:(ID)object;- (voID)performAction;@end@implementation MenuItem - (voID)performAction{    if (self.target && self.action)    {      if (self.object)      {        [self.target performSelector:self.action withObject:self.object];      }      else      {        [self.target performSelector:self.action];      }    }}@end@interface Widget : NSObject- (voID)someMethod:(ID)sender;@end

在某些时候,我实例化一个MenuItem:

MenuItem *item = [MenuItem alloc] initWithTarget:Widget action:@selector(someMethod:) object:nil];

然后在其他地方,我在菜单项上调用performAction:

[item performAction];

执行某些方法我遇到崩溃:

@implementation Widget- (voID)someMethod:(ID)sender{  // EXEC_BAD_ACCESS crash in objc_retain}@end

为什么会这样?

解决方法 崩溃的原因是因为我使用了错误的performSelector.

NSObject定义了多个版本的performSelector.我正在援引的是:

- (ID)performSelector:(SEL)aSelector;

但是,我正在调用的方法使用了一个ID参数.例如:

- (voID)someMethod:(ID)sender;

现在,ARC是一个很好的安全内存管理系统,它正在尝试确保在执行方法期间适当地保留参数.所以即使我的someMethod:是空的ARC生产的代码看起来像这样:

- (voID)someMethod:(ID)sender {    objc_retain(sender);    objc_release(sender);}

然而,这个问题是我正在调用performSelector:而不是为sender参数提供一个值.所以发件人指着堆栈上的随机垃圾.因此,当调用objc_retain()时,应用程序崩溃.

如果我改变:

MenuItem *item = [[MenuItem alloc] initWithTarget:Widget                                           action:@selector(someMethod:)                                           object:nil];

MenuItem *item = [[MenuItem alloc] initWithTarget:Widget                                           action:@selector(someMethod)                                           object:nil];

- (voID)someMethod:(ID)sender;

- (voID)someMethod;

然后崩溃消失了.

同样,我也可以改变

[self.target performSelector:self.action];

[self.target performSelector:self.action withObject:nil];

如果我想遵循采用单个参数的“标准”形式的目标动作方法. performSelector的第二种形式的好处是,如果我正在调用一个不接受参数的方法,它仍然可以正常工作.

总结

以上是内存溢出为你收集整理的xcode – 使用performSelector执行的方法中的objc_retain中的崩溃全部内容,希望文章能够帮你解决xcode – 使用performSelector执行的方法中的objc_retain中的崩溃所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1106274.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-28
下一篇 2022-05-28

发表评论

登录后才能评论

评论列表(0条)

保存