为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在IOS中用前导下划线重命名合成属性?

为什么在IOS中用前导下划线重命名合成属性?

iOS
翻阅古今 2019-07-27 15:15:20
为什么在IOS中用前导下划线重命名合成属性?在Xcode 4中创建新项目时,样板代码在合成实现文件中的IVAR时添加一个下划线字符,如下所示:@synthesize window = _window;或:@synthesize managedObjectContext = __managedObjectContext;有人能告诉我这里取得了什么成就吗?我不是一个完全的裸体,但这是目标的一个方面-C我不明白。另一个困惑之处是:在应用程序委托实现中,在如前所述合成窗口Ivar之后,在应用程序dfinishLaunchingWithOptions:Method中,使用Self引用了窗口和viewController Ivars:self.window.rootViewController = self.viewController[self.window makeKeyAndVisible];但是在dealloc方法中它是_Window或_viewController谢谢
查看完整描述

3 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

这是Object-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相反,使用访问器方法应该是这样的(尽管我不推荐它,原因我稍后会解释):

- (void)dealloc {
  self.qux = nil; // [self setQux:nil];
  [super dealloc];}

这有释放的效果qux,并将引用归零。但这可能会带来不幸的副作用:

  • 您可能最终会触发一些意外的通知。其他对象可能正在观察对

    qux

    ,在使用访问器方法更改访问器方法时记录。
  • (并不是每个人都同意这一点:)像访问器那样将指针归零可能会隐藏程序中的逻辑错误。如果您曾经访问对象的实例变量

    对象已被解除分配,您正在做一些严重错误的事情。因为目标-C

    nil

    -消息传递语义,但是,您永远不会知道,已经使用访问器设置为

    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(翻译成self->qux在C语法中,用于从指针访问成员)。当您想要使用访问器方法(这将通知观察者,并做其他有趣的事情,并使事情更安全和更容易与内存管理),使用self.qux ([self qux])和self.qux = blah; ([self setQux:blah]).

可悲的是,苹果的示例代码和模板代码糟糕透了。永远不要用它作为正确的目标-C风格的指南,当然也不要用它作为正确的软件体系结构的指南。*)






查看完整回答
反对 回复 2019-07-28
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

这是另一个原因。在不突出实例变量的情况下,您经常会得到带有参数的警告。self.title = titleself.rating = rating:

@implementation ScaryBugData@synthesize title;@synthesize rating;- (id)initWithTitle:(NSString *)title rating:(float)rating {
    if (self = [super init]) {
        self.title = title; // Warning. Local declaration hides instance variable
        self.rating = rating; // Warning. Local declaration hides instance variable
    }
    return self;}@end

您可以通过对实例变量打分来避免警告:

@implementation ScaryBugData
    @synthesize title = _title;
    @synthesize rating = _rating;
    - (id)initWithTitle:(NSString *)title rating:(float)rating {
        if (self = [super init]) {
            self.title = title; // No warning
            self.rating = rating; // No warning
        }
        return self;
    }
    @end




查看完整回答
反对 回复 2019-07-28
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

在DIDFinishLaunchingWithOptions:Method应用程序中,使用Self引用窗口和viewControllerIvars

不,他们不是。这些都是对特性 windowviewController..这就是下划线的要点,以便使属性在使用时(不使用下划线)和IVAR被直接访问(带有下划线)时更加清晰。




查看完整回答
反对 回复 2019-07-28
  • 3 回答
  • 0 关注
  • 307 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信