在iOS上的Objective-C中,使用合成getter时"self.foo"和"foo"之间的(样式)区别是什么?

mak*_*dad 13 getter setter properties objective-c

我搜索了很多关于ObjC访问器和合成访问器的问题都无济于事.这个问题更像是"帮我解决问题"的问题; 我不期待一个答案,但我宁愿寻找专家来衡量这个论点.

在Cocoa Touch类中,我会写一些像这样的代码(其中soundEffects是一个合成的NSArray属性):

id foo = [self.soundEffects objectAtIndex:1];
Run Code Online (Sandbox Code Playgroud)

一位同事让我解释为什么上述内容比这一行更好:

id foo = [soundEffects objectAtIndex:1];
Run Code Online (Sandbox Code Playgroud)

好吧,功能上,它没有什么不同.

我对前者的论点如下:

  1. self.soundEffects 告诉处理代码的所有其他编码人员,这是一个iVar,而不是本地范围的变量.

  2. 如果我们需要,我们可以在soundEffectsgetter访问器中放置自定义逻辑.

  3. 没有具体的理由,在Obj-C工作一年后,它"感觉"是正确的做法.

他接受参数#1和#2是有效的,但也给出了对应点:

  1. 这不仅仅是代码臃肿吗?

  2. 一个类不应该被允许直接与自己的iVars交谈,而不必自己调用方法(getter)吗?

任何接受者?

Lou*_*nco 9

我个人已经决定使用下划线前缀来进行ivars,这种合成

@synthesize name = _name;
Run Code Online (Sandbox Code Playgroud)

这样我就不会把它们搞混了.不使用self的主要问题是这段代码

_name = ...
Run Code Online (Sandbox Code Playgroud)

与...非常不同

self.name = ...
Run Code Online (Sandbox Code Playgroud)

当@property使用retain选项时.第一个不保留对象,第二个调用保留的合成setter.

唯一一次产生重大影响的是分配,所以我倾向于一直使用self.所以我确保我在分配时这样做.

  • 如果你在Cocoa框架中使用那个领先的下划线,请小心.Apple保留使用类iVars的前导下划线,您可能会遇到为子类的iVar选择相同名称的问题. (3认同)

wal*_*lky 5

你1点是不完全正确:self.soundEffects不是伊娃,虽然它可能会发生,给你一些东西, -因为它在你的合成的情况下NSArray,在此刻.

这反过来意味着您的第2点是问题的关键 - 如果您通过访问器路由所有访问,那么一切都很好地封装,您可以随后修改实现,而不必担心副作用.

当您使用mutator时,这也是一种很好的做法,因此您可以保持一致的内存管理.

在大多数情况下,我会说这是最好通过路由self.property的一切一个属性,并限制事情是严格内部直接伊娃访问.但是,我承认在某些情况下 - 特别是对于那些不使用retain/ copy语义的东西- 它可能更像是一种风格偏好.