1

我已经在不同的来源阅读过这样的问题:书籍、文章等,但无法理解它。当出现支持 i-var 和属性的问题以及如何解决它时,您能举个例子吗?我已经从这里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? 在任何其他设置方法中?

4

1 回答 1

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;

您根本没有使用二传手。

self.ponyName = name;

将解决该问题,name并将由二传手复制。


讨论

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

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

一个在 ARC 下仍然有效的例子是当你声明一个copy属性时。在这种情况下,合成的 setter 将在分配给 ivar 之前负责复制参数,所以当你这样做时

[self setMyCopyProperty:aNewThing];

或等效地

self.myCopyProperty = aNewThing;

aNewThingcopy在分配给支持的 ivar 之前,将收到一条消息。

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

@synthesize myCopyProperty;

你可能会不小心发现自己在做

myCopyProperty = aNewThing;

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

为了不混淆 ivars 和辅助方法,它成为一个标准约定,即在 ivars 前加上下划线,即像这样合成它们

@synthesize myCopyProperty = _myCopyProperty;

这样一来,如果你不小心做了

myCopyProperty = aNewThing;

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

_myCopyProperty = [aNewThing copy];

这对于您不使用 setter 的意图更加明确。

最后,可能值得注意的是,使用现代版本的clang编译器,您可以避免显式@synthesize,因为它会以以下形式自动插入

@synthesize foo = _foo;

有一些例外情况,您可以在此处阅读更多相关信息:我何时应显式使用 @synthesize?

于 2013-11-14T16:24:55.523 回答