在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中保留的,我的问题是为什么编译器不抱怨它是否被允许?相反,它生成了错误的代码。
答案 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。)