我正在使用在Xcode中选择拆分视图应用程序时创建的标准样本拆分视图,添加几个字段后,我需要添加一些字段以在详细视图中显示它们。 / p>
发生了一些有趣的事情 在原始样本中,主视图在详细视图中设置“detailItem”属性,详细视图显示它。
- (void)setDetailItem:(id) newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
我明白这是做什么的,所以当我在玩它时。我认为如果不使用_detailItem我会使用self.detailItem,因为它是类的属性。
然而,当我使用
时self.detailItem != newDetailItem
我实际上卡在一个循环中,这个方法经常被调用,我不能在模拟器中做任何其他事情。
我的问题是,下划线变量(ivar?)和属性之间的实际差异是什么? 我在这里阅读了一些帖子似乎只是一些客观的C约定,但实际上它有所不同。
答案 0 :(得分:41)
_property
表示您正在直接访问该物业。
self.property
表示您正在使用访问者。
在你的情况下,在你调用它的setter方法中,创建一个递归调用。
答案 1 :(得分:6)
在您的实验过程中,您已经设置了无限循环,这就是模拟器无响应的原因。
在self.detailItem
调用setDetailItem:
的范围内以递归方式调用setDetailItem:
,因为您的类为属性detailItem
实现了自定义setter方法。
我会引用你关于属性,ivars等scoop的声明属性的Apple documentation;但简单地说,声明的属性是为您的类提供访问器方法的简化方法。它们不是必须编写您自己的访问器方法(就像我们在Objective-C 2.0之前所做的那样),而是通过属性语法为您生成它们。
答案 2 :(得分:5)
这些属性基本上是编译器为给定实例变量生成 setter 和 getter 的一种方式。
所以当你使用类似的东西时:
id detailItem = self.detailItem;
你在幕后做的是:
id detailItem = [self detailItem];
同样的:
self.detailItem = otherDetailItem;
将是:
[self setDetailItem:otherDetailItem];
所以当你自己编写setter时,你会进入一个无限循环,因为你自己访问方法本身。 你可以自由地利用'自我'。因为我上面描述的机制,你的班级中的符号,而不是当你覆盖了setter或accessor时。
我使用的课程中的案例。简单地访问ivar的注意事项是当我更改值时,你不会在课堂内知道更改值时需要发生什么。你有什么状态可以通知某个代表状态发生了变化吗?但通常情况并非如此,只需使用。表示你确定将来你不必重构某些代码,如果你决定在你的setter方法中做一些魔术。
答案 3 :(得分:2)
我将做一个例子(没有启用ARC):
@property (nonatomic, retain) NSNumber* number;
如果你没有合成它,你可以这样访问它:
self.number= [NSNumber numberWithBool: YES];
这种情况下,数字会被保留。如果您合成它而不使用该属性:
@synthesize number;
稍后在文件中:
number=[NSNUmber numberWithBool: YES];
您尚未使用该属性,因此不会保留该数字。这在使用访问器和合成属性之间存在相关差异。