IOS: использование self и подчеркивания (_) с переменной

Возможный дубликат:
Как работает подчеркивание перед переменной в классе target-c cocoa?

Я был очень смущен использованием self или подчеркивания с именем переменной после ее синтеза, как показано ниже:

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

In .m file:
@synthesize users = _users;

Исходя из моего понимания, когда я использую self.users, ОС обязательно освободит ранее выделенную память в методе set, поэтому нам не нужно заботиться об этом явно.

_users является переменной экземпляра для пользователей и должна обычно использоваться при доступе к переменной users. Если я использую _users для изменения его значения, то он не будет _users который не будет уведомлять класс, наблюдающий за изменением значения пользователя.

Кроме того, self.users позволяет дифференцировать фиктивную переменную в имени метода, как self.users ниже,

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

Может кто-нибудь сказать мне, если я что-то неправильно понял или пропустил при использовании _users или self.users?

Ответ 1

Я думаю, что это помогает рассмотреть, как свойства (или могут быть реализованы) компилятором.

Когда вы пишете 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:

Ответ 2

когда вы используете self.users, вы получаете доступ к свойству через установщик или получатель.

когда вы используете _users, вы получаете доступ к свойству, которое непосредственно пропускает установщик или получатель.


вот хорошая демонстрация этого:

- (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
}

это и точка в случае геттера.


об управлении основной памятью (в случае MRR или ARC): iOS отключит объект, если нет более сильного указателя, который сохраняет его, независимо от того, как вы освободите указатель объектов.

Ответ 3

Да, это очень правильно. Несколько второстепенных моментов:

iOS автоматически не выпускает объект только потому, что вы используете точечную нотацию. Он освобождает объект, когда свойство объявляется как copy или retain (или strong в ARC). Если, например, вы используете не-ARC-код, и свойство объявляется как assign, он не освободит объект.

С последней версией инструментальной цепочки разработчика (Xcode 4.4+) вам больше не нужно вручную синтезировать свойства - они автоматически синтезируются (с лидирующим подчеркиванием).