【问题标题】:iOS: Usage of self and underscore(_) with variable [duplicate]iOS:self和下划线(_)与变量的用法[重复]
【发布时间】:2012-08-23 21:41:16
【问题描述】:

可能重复:
How does an underscore in front of a variable in a cocoa objective-c class work?

在如下合成变量名后,我一直对使用 self 或带下划线的变量名感到非常困惑:

In .h file:
@property(nonatomic, strong) NSMutableArray *users;

In .m file:
@synthesize users = _users;

根据我在使用self.users时的理解,操作系统会确保在set方法中释放之前分配的内存,所以我们不需要显式处理。

_users 是用户的实例变量,应该在访问用户变量时正常使用。如果我使用_users 更改它的值,那么它不会触发 KVO 委托,它不会通知观察用户值变化的类。

此外,self.users 允许在方法名称中区分虚拟变量,如下所示,

- (void)assignUsers:(NSMutableArray*)users {
      self.users = users;
}

有人可以告诉我在使用_usersself.users 时是否有任何我理解错误或遗漏的地方?

【问题讨论】:

  • 嗨@qegal 我浏览了那个帖子,如果你读了我的问题,大部分点都是结论点,但我不知道什么时候使用什么!

标签: ios objective-c memory-management self


【解决方案1】:

当您使用self.users 时,您可以通过setter 或getter 访问该属性。

当您使用_users 时,您可以直接跳过setter 或getter 访问属性。


这是一个很好的演示:

- (void)setUsers:(id)users {
    self.users = users; // WRONG : it causes infinite loop (and crash), because inside the setter you are trying to reach the property via setter
}

- (void)setUsers:(id)users {
    _users = users; // GOOD : set your property correctly
}

这也是 getter 的重点。


关于基本内存管理(MRRARC):如果没有更多的强指针保持对象存活,iOS 将释放对象,无论你如何释放对象的指针。

【讨论】:

  • 亲爱的投反对票的人!我很荣幸能得到一些反馈,说明为什么你的手在否决投票按钮上方颤抖,因为——不管你信不信——我不是一个读心术的人来弄清楚它。谢谢!
  • 我完全不知道你的意思是什么:“你表现出滥用self和......”,你能详细说明一下吗? good demo 展示了绕过和调用 setter 内的 same setter 之间的区别,这会导致无限递归循环,并且在堆栈溢出——因此最后的方法是避免在运行时造成无限循环。
【解决方案2】:

我认为考虑编译器如何(或可能)实现属性会有所帮助。

当您编写 self.users = array; 时,编译器会将其转换为 [self setUsers:array]; 当您编写 array = self.users; 时,编译器会将其转换为 array = [self users];

@synthesize 将 ivar 添加到您的对象(除非您自己添加),并为您实现 -users-setUsers: 访问器方法(除非您提供自己的)

如果您使用 ARC-setUsers: 将类似于:

- (void)setUsers:(NSArray *)users
{
    _users = users; // ARC takes care of retaining and release the _users ivar
}

如果您使用 MRC(即未启用 ARC),-setUsers: 将类似于*:

- (void)setUsers:(NSArray *)users
{
    [users retain];
    [_users release];
    _users = users;
}

* - 请注意,这是-setUsers:的一个简化的非原子实现@

【讨论】:

  • 关于这个主题的唯一答案是从引用计数的角度以如此优雅的方式谈论差异。很棒。
【解决方案3】:

是的,这非常正确。几个小问题:

iOS 不会因为您使用点符号而自动释放对象。当属性声明为copyretain(或ARC 中的strong)时,它会释放一个对象。例如,如果您使用的是非 ARC 代码并且该属性被声明为 assign,则它不会释放该对象。

使用最新版本的开发工具链(Xcode 4.4+),您不再需要手动合成属性 - 它们会自动合成(带有前导下划线)。

【讨论】:

猜你喜欢
  • 2011-10-19
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多