目标C强调财产与自我

Pit*_*ita 16 objective-c

我正在使用在Xcode中选择拆分视图应用程序时创建的标准样本拆分视图,添加几个字段后,我需要添加一些字段以在详细视图中显示它们.

在原始样本中发生了一些有趣的事情,主视图在详细视图中设置了"detailItem"属性,详细视图显示了它.

- (void)setDetailItem:(id) newDetailItem
{
if (_detailItem != newDetailItem) {
    _detailItem = newDetailItem;

    // Update the view.
    [self configureView];
}
Run Code Online (Sandbox Code Playgroud)

我理解那是什么以及所有,所以当我在玩它时.我认为如果不使用_detailItem我会使用self.detailItem,因为它是类的属性.

但是,当我使用

self.detailItem != newDetailItem
Run Code Online (Sandbox Code Playgroud)

我实际上卡在一个循环中,这个方法经常被调用,我不能在模拟器中做任何其他事情.

我的问题是,下划线变量(ivar?)和属性之间的实际差异是什么?我在这里看了一些帖子似乎只是一些客观的C约定,但它实际上有所不同.

Ano*_*dya 41

_property 意味着您直接访问该物业.

self.property 意味着您正在使用访问者.

在您的情况下,在调用它的setter方法中,创建一个递归调用.


Flu*_*imp 6

在您的实验过程中,您已经设置了无限循环,这就是模拟器无响应的原因.

由于您的类为属性实现了自定义setter方法,因此在递归调用self.detailItem范围内setDetailItem:调用.setDetailItem:detailItem

我会向您推荐关于属性,ivars等上的scoop声明属性的Apple文档 ; 但简单地说,声明的属性是为您的类提供访问器方法的简化方法.它们不是必须编写自己的访问器方法(就像我们在Objective-C 2.0之前必须做的那样),而是通过属性语法为您生成它们.


Ant*_*udt 5

这些属性基本上是编译为给定实例变量生成settergetter的一种方式.

所以当你使用类似的东西:

id detailItem = self.detailItem;
Run Code Online (Sandbox Code Playgroud)

你在幕后做的是:

id detailItem = [self detailItem];
Run Code Online (Sandbox Code Playgroud)

同样的:

self.detailItem = otherDetailItem;
Run Code Online (Sandbox Code Playgroud)

将会:

[self setDetailItem:otherDetailItem];
Run Code Online (Sandbox Code Playgroud)

所以当你自己编写setter时,你会进入一个无限循环,因为你自己访问方法本身.你可以自由地利用'自我'.因为我上面描述的机制,你的班级中的符号,而不是当你覆盖了setter或accessor时.

在我使用的类中的案例.简单地访问ivar的注意事项是当我更改值时,你不会在课堂内知道更改值时需要发生什么.你有什么状态可以通知某个代表状态发生了变化吗?但通常情况并非如此,只需使用.表示你确定将来如果你决定在你的setter方法中做一些魔术,你将不必重构一些代码.