这个问题已经在这里有了答案:
已关闭8年。
在Xcode 4中创建新项目时,样板代码在将实现文件中的ivars合成为以下内容时会添加下划线字符:
@synthesize window = _window;
或者:
@synthesize managedObjectContext = __managedObjectContext;
有人可以告诉我这里正在完成什么吗?我不是一个完整的小伙子,但这是我不了解的Objective-C的一个方面。
另一个困惑点;在应用程序委托(delegate)实现中,按照上述方法合成窗口iVar之后,在应用程序didFinishLaunchingWithOptions:方法中,使用self来引用window和viewController ivars:
self.window.rootViewController = self.viewController
[self.window makeKeyAndVisible];
但是在dealloc方法中,它是_window或_viewController
谢谢
最佳答案
这是Objective-C运行时的早期版本的工件。
最初,@synthesize
用于创建访问器方法,但运行时仍要求必须显式实例化实例变量:
@interface Foo : Bar {
Baz *_qux;
}
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
@end
人们会在其实例变量前面加上前缀,以区别于它们的属性(即使Apple不想让您使用下划线,但这是另一回事)。您综合属性以指向实例变量。但关键是,
_qux
是一个实例变量,self.qux
(或[self qux]
)是发送给对象qux
的消息self
。我们直接在
-dealloc
中使用实例变量;相反,使用accessor方法看起来像这样(尽管我不建议这样做,出于稍后将解释的原因):- (void)dealloc {
self.qux = nil; // [self setQux:nil];
[super dealloc];
}
这具有释放
qux
以及清零引用的作用。但这可能会有不利的副作用:qux
的更改,这些更改在使用访问器方法进行更改时被记录。 nil
-messaging语义,使用访问器设置为nil
永远不会知道。如果您直接释放了实例变量且未将引用归零,则访问已释放的对象将导致发出巨大的EXC_BAD_ACCESS
。 更高版本的运行时除了访问器方法外还添加了合成实例变量的功能。使用这些版本的运行时,上面的代码可以省略实例变量来编写:
@interface Foo : Bar
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
@end
实际上,这会在
Foo
上合成一个名为_qux
的实例变量,可通过getter和setter消息-qux
和-setQux:
访问该实例变量。我建议不要这样做:虽然有点困惑,但是使用下划线是有充分的理由的;即,防止意外的直接ivar访问。如果您认为自己可以记住使用的是原始实例变量还是访问器方法,则可以这样做:
@interface Foo : Bar
@property (retain) Baz *qux;
@end
@implementation Foo
@synthesize qux;
- (void)dealloc {
[qux release];
[super dealloc];
}
@end
然后,当您想直接访问实例变量时,只需说出
qux
(将其转换为C语法中的self->qux
以便从指针访问成员)。当您要使用访问器方法(它将通知观察者,并执行其他有趣的事情,并使事情在内存管理方面更安全,更轻松)时,请使用self.qux
([self qux]
)和self.qux = blah;
([self setQux:blah]
)。可悲的是,Apple的示例代码和模板代码很烂。永远不要将其用作适当的Objective-C风格的指南,当然也绝不要将其用作适当的软件体系结构的指南。 :)