1

在 XCode 4.6.2 ARC 中,如果您在名为 'retain' 的类中有一些属性,IDE 或编译堆栈都会做一些有趣的事情,使该类不能以通常的模式使用:[[MyClass alloc] init].

例如,如果我将 Foo 类定义为

// Foo.h

#import <Foundation/Foundation.h>

@interface MosquittoMessage : NSObject

@property (nonatomic, assign) BOOL retain;

-(id)init;

@end

// Foo.m

#import "Foo.h"

@implementation MosquittoMessage

-(id) init
{
  self = [super init];
  return self;
}

@end

它将编译并运行,但是,我不能使用

Foo *foo = [[Foo alloc] init];

创建 foo。上面的运行时语句会将 foo 设置为 nil。我使用调试器跟踪问题,发现 alloc 实际上返回了一个有效的 Foo,但在 init 内部,由于某种原因它被释放,返回的 self 为 nil。

有人对 XCode 或编译系统中的这个“错误”有任何想法吗?

添加:

当然'retain'在Obj-C中被保留,我的问题是如果不允许编译器为什么不抱怨?相反,它生成了错误的代码。

4

2 回答 2

5

属性只是方法调用的语法糖。所以一个retain属性意味着一个retain方法。但是已经retain方法了,ARC是禁止调用的。

您所遇到的实际情况是,Objective-C 中的所有内容都是一个巨大的命名空间。您不希望任何东西与已经存在的东西具有相同的名称 - 您可能会产生名称冲突,最好的情况是收到警告,或者最坏的情况是破坏您的应用程序的功能。我曾经通过命名一个属性来破坏我的应用程序firstResponder;尽管没有公共方法有这个名字,但显然这种方法在幕后存在,我不小心颠覆了它。

于 2013-05-13T00:42:00.797 回答
2

retain是 NSObject 的一个方法。

- (id)retain;

在幕后,ARC 可能会在编译之前将您的代码更改为以下内容。

Foo *foo = [[[Foo alloc] init] retain];

但是通过设置一个名为 retain 的 BOOL 属性,你已经告诉编译器有一个

- (BOOL)retain;

因此,与其为 foo 分配由 NSObject 的 retain 方法返回的 id,不如为其分配由您的 retain 方法返回的 BOOL。如果您还没有定义方法,请使用 iVar _retain 中的 nil。

[编辑]您没有收到错误,因为用您自己的替换重载超类方法是完全合法的。在这种情况下不是很有用。

这似乎不是一个问题。所有语言都有不应该使用的保留字。可以将 NSObject 的方法视为保留字列表的一部分。(认为​​它实际上不是 Obj-C 的保留字。NSObject 是 Apple API 的一部分,而不是 Obj-C 本身。)

于 2013-05-13T00:53:47.340 回答