为什么我在使用XCode时不能拥有名为'retain'的属性?

时间:2013-05-13 00:39:34

标签: ios objective-c xcode automatic-ref-counting clang

在XCode 4.6.2 ARC中,如果在名为“retain”的类中有一些属性,则IDE或编译堆栈会做一些有趣的事情,使得该类不能以通常的模式使用:{{ 1}}。

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

[[MyClass alloc] init]

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

// 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设置为nil。我使用调试器跟踪问题并发现alloc实际上返回了一个有效的Foo,但是在init中,由于某种原因它被释放,并且返回的self是nil。

任何人都对XCode或编译系统中的'bug'有任何想法?

增加:

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

2 个答案:

答案 0 :(得分:5)

属性只是方法调用的语法糖。因此,retain属性意味着retain方法。但是已经一个retain方法,并且禁止您通过ARC调用它。

您遇到的实际情况是Objective-C中的所有内容都是一个庞大的命名空间。您不希望任何与已存在的内容具有相同的名称 - 您可能会发生名称冲突,并且最多会收到警告或最坏情况下破坏应用程序的功能。我曾经通过命名属性firstResponder来破坏我的应用程序;即使没有 public 方法有这个名字,显然这样的方法存在于幕后,我不小心颠覆了它。

答案 1 :(得分: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。

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

这似乎不是一个问题。所有语言都保留了您不应使用的单词。人们可以认为NSObject的方法只是保留单词列表的一部分。 (认为​​它实际上并不是Obj-C的保留字.NSObject是Apple API的一部分,而不是Obj-C。)