1

我阅读了很多关于这个主题的帖子,但我无法完全理解所有内容。好的,很明显

self.text = @"MyText" will call the accessory method setText (autogenerated)

_text = @"MyText" will still assign the value but will not call the setText

这很清楚。

但这在我们不使用 ARC 时很有用,因为 setText 会负责内存管理。但是当我们使用 ARC 时会发生什么?有时,如果我使用 _text 一切正常,有时如果我不使用“self.text”,我的应用程序将无法工作。

那么真正的区别是什么?必须有比内存管理更多的东西。

假设我有这个

@interface MyClass:NSObject { 
  NSMutableString *text; 
}

@property (nonatomic ) NSMutableString *text;

在这种情况下,这不是同一个电话吗

self.text = @"ok" 

或者

text = @"ok" ?

有什么不同?

4

6 回答 6

7

该属性的底层实例变量实际上是 _text。这就是自动合成属性的工作原理。

但是,您应该考虑使用访问器来设置属性(使用 self.text = 代替)。有关在目标 c 中使用 ivars 与属性的原因的更多信息,请参阅此链接

于 2013-09-05T08:53:21.770 回答
4

self.text[self text](或者[self setText:...],如果在作业的左侧)的语法糖,并且是一条消息;当它被自动生成(“合成”)时,它将返回连接的实例变量的值。_text是这个实例变量。

您只能访问类中的实例变量。您可以从任何地方发送消息。如果有一天您希望修改 text 属性的内部工作,以便它不会简单地返回局部变量的值,则这种区别很重要。

于 2013-09-05T08:48:39.403 回答
4

答案就在这里,我真的需要变量和属性吗?

当您 @property 时,您实际上是在创建用于访问和变异的方法以及实例变量。

所以当你有 @property (nonatomic, strong) NSString *text; 您创建一个 iVar _text 和两个方法:

self.text; //will call -(NSString *)text;
self.text = @"text here"; //is calling -(void)setText:(NSString *)text;

@property 用于剥离样板代码,它减少了编写类所需的代码行数。

当然,现在在 ARC 环境中有时调用 self.text = @"ok" 和 _text = @"ok" 是可以的,但你没有得到 -(NSString *)text; 和 -(void)setText:(NSString *)text; 在您的公共头文件中。

此外,调用 self.text 和 self.text = 或它们的等价物 [self text] [self setText:] 通常是一种很好的做法,因为您可能已经覆盖了文本实现:

-(NSString *)text{
    return [NSString stringWithFormat@"%@.jpg", _text];
}

-(void)setText:(NSString *)text{
    _text = [NSString stringWithFormat:@"DW%@", text];
}

所以当你这样做时:

self.text = @"HelloThere";
NSLog (@"%@", self.text); //This will return DWHelloThere.jpg
NSLog (@"%@", _text); //Will return DWHelloThere
//whereas
_text = @"HelloThere";
NSLog (@"%@", _text); //Will return HelloThere

所以@property 可以为您节省大约 8 行代码,让您自己的类保持整洁,如果需要,您可以覆盖访问器和修改器。但是由于后一点,它的良好做法是调用 self.text 和 self.text = @"so and so" 而不是仅仅访问 iVar 本身。

于 2013-09-05T08:51:35.183 回答
2

从概念上讲,区别仅在于在一种情况下向对象发送消息或在另一种情况下更改单个 ivar。内存管理故事只是一个必要的内务管理,如果您使用它,则由 ARC 为您处理。

如果您对道德故事感兴趣,请在此处阅读 Jon Reid 的帖子:Objective-C 中的点符号:100% Pure Evil http://qualitycoding.org/dot-notation/

旁注:尽可能使用 ARC。它会在大多数情况下正确地自动处理保留释放周期(尽管访问块中的 self 应该小心处理。)如果您使用 ARC,这两种方法之间没有区别,保留计数将被正确处理。正如你所描述的,没有ARC,你必须确保在属性设置之后,必须释放对象,而在访问ivar时这不是必需的。这篇文章中描述了更多关于一些实践的信息:Objective-C 中的属性和内存管理 http://www.whilethis.com/2011/04/properties-and-memory-management-in-objective-c/

于 2013-09-05T09:04:35.670 回答
1

真正的区别在于:

当您在代码中创建实例时,您有一个名为 text 的变量。相反,当您在文本上使用该属性时,它将创建一个名为 _text 的 iVar。

你可以想象,调用一个或另一个,会有很大的不同,因为它们是两个完全不同的变量

于 2013-09-05T09:05:51.083 回答
1

self.text = @"Something"_text使用访问器方法访问您的私有变量[self setText:@"Something"]。点符号只是一种语法糖。此方法可以有自己的实现,为仅设置私有变量的值添加额外的功能_text

_text = @"Something"直接将值设置为私有变量本身。

此外,在text类实现之外设置属性值时,[instance setText:@"Something"]会自动调用访问器来设置私有变量的值


让我向您展示一个简单的例子,可能有什么不同。该方法的实现很简单,仅出于教育目的,因此在实际代码中可能没有意义:-)

想象一下,您想在每次text属性值更改时向控制台记录一条消息。您可以通过覆盖访问器方法来完成此操作- (void)setText:(NSString *)text,例如:

- (void)setText:(NSString *)text
{
    //  You can do whatever you want with the input "text" value, validate the value for example
    //  Here we just log the text was changed
    //  In the log message, we still have the old value of the "text" in the private variable "_text"
    //  so we can log it together with the new value
    NSLog(@"Value of \"text\" property changed from \"%@\" to \"%@\"", _text, text);

    //  Set the new value of the private variable
    _text = text;

    //  From here on, the private variable already has new value and the log line above
    //  would give the same values between from and to quotes
    NSLog(@"Value of \"text\" property is now \"%@\"", _text);
}

因此,当您_text直接设置时,不会执行上述任何日志消息,因为您直接访问该变量。

另一方面,使用访问器方法设置self.text = @"Something"会导致以下内容打印到控制台:

Value of "text" property changed from "(null)" to "Something"
Value of "text" property is now "Something"
于 2013-09-05T09:10:39.257 回答