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+) вам больше не нужно вручную синтезировать свойства - они автоматически синтезируются (с лидирующим подчеркиванием).