支持的实例变量和属性的示例。它与'自我'有关吗?

时间:2013-11-14 16:05:52

标签: objective-c self

我已经从不同的来源读到了这样的问题:书籍,文章等,但却无法理解它。当支持的i-vars和属性问题出现以及如何解决时,你能举个例子吗? 我已经从这里http://blog.bignerdranch.com/463-a-motivation-for-ivar-decorations阅读了以下代码。

@property (copy) NSString *name;
...
@synthesize name;
...
- (void) setPonyInfoFromPropertyDict: (NSDictionary *) ponyProperties {
    NSString *name = [ponyProperties objectForKey: @"Name"];
    ponyName = name; //self.ponyName=name should solve the problem? 
}

NSMutableString *mutableName = [NSMutableString stringWithString: @"Mikey"];
NSDictionary *ponyProperties = [NSDictionary dictionaryWithObject: mutableName  
                               forKey: @"Name"];
[pony setPonyInfoFromPropertyDict: ponyProperties];
[mutableName setString: @"Wookiee"]; 

该代码和文章是否与此问题有关? 正确的方法是使用self.ponyName = name?在任何其他设置方法?

1 个答案:

答案 0 :(得分:1)

我认为这个例子是错误的,或者是不合适的。一个恰当的例子应该是

@property (copy) NSString *ponyName; // not name!
...

@synthesize ponyName; // not name!
...
- (void) setPonyInfoFromPropertyDict: (NSDictionary *) ponyProperties {
    NSString *name = [ponyProperties objectForKey: @"Name"];
    ponyName = name;
    //self.ponyName = name; // will solve the problem 
}

name可以是一个可变字符串,因此如果你想确保它在分配后不会改变,你必须复制它。您可以使用copy属性执行该任务,但执行

ponyName = name;

你根本就没有使用过setter。

self.ponyName = name;

将解决问题,并且name将被设置者复制。


讨论

在Objective-C中编程时最常见的错误之一是直接访问ivar而不是使用setter / getter。

附件方法非常重要,因为它们通常为访问和设置ivars提供了大量逻辑,最值得关注的是内存管理。如今,ARC编译器大大简化了它们的实现,但是,如果您使用MRC,附件方法对于帮助处理release / retain平衡至关重要。

在ARC下仍然有效的示例是当您声明copy属性时。在这种情况下,合成的setter会在分配到ivar之前复制参数,所以当你这样做时

[self setMyCopyProperty:aNewThing];

或等效

self.myCopyProperty = aNewThing;
在被分配到支持的ivar之前,

aNewThing会收到copy消息。

另一方面,如果您合成这样的属性

@synthesize myCopyProperty;

你可能会意外地发现自己在做什么

myCopyProperty = aNewThing;

不会复制aNewThing,因为您直接访问了ivar。

为了不混淆ivars和附属方法,然后将ivars加上下划线成为标准惯例,即将它们合成为

@synthesize myCopyProperty = _myCopyProperty;

这样,如果你不小心做了

myCopyProperty = aNewThing;

它不会编译,因为没有myCopyProperty ivar这样的东西,在你调试与内存相关的问题时可能会让你免于头痛。如果您知道自己在做什么并且您真的想要访问ivar(可能是init方法),那么您可以简单地执行

_myCopyProperty = [aNewThing copy];

更明确地说明了你不使用二传手的意图。

最后,值得注意的是,使用clang编译器的现代版本,您可以避免使用显式@synthesize,因为它将以

的形式自动插入
@synthesize foo = _foo;

有一些例外适用,您可以在此处详细了解:When should I use @synthesize explicitly?