Objective-C - Когда использовать 'self'
Это немодифицированный код из шаблона Apple Utility Aplication:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MainViewController *aController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
self.mainViewController = aController;
[aController release];
mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
[window addSubview:[mainViewController view]];
[window makeKeyAndVisible];
}
Когда mainViewController
назначается aController
, указано ключевое слово self
:
self.mainViewController = aController;
Однако, когда установлен кадр mainViewController
, ключевое слово self
не требуется:
mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
Если я удалю ключевое слово self
из первого примера, программа выйдет из строя с сообщением:
objc[1296]: FREED(id): message view sent to freed object=0x3b122d0
Если я добавлю ключевое слово self
ко второму примеру, программа будет работать нормально.
Может ли кто-нибудь объяснить, почему self
требуется в первом случае, но не во втором? Я предполагаю, что в обоих случаях mainViewController
ссылается на ту же переменную экземпляра.
Ответы
Ответ 1
Использование self заставляет "setter" вашего класса "вызывать" эту переменную, а не напрямую менять ivar.
self.mainViewController = aController;
эквивалентно:
[self setMainViewController:aController];
С другой стороны:
mainViewController = aController;
просто изменяет непосредственно переменную экземпляра mainViewController
, пропуская любой дополнительный код, который может быть встроен в метод UIApplication setMainViewController
, например, удаление старых объектов, сохранение новых, обновление внутренних переменных и т.д.
В случае, когда вы получаете доступ к кадру, вы все еще вызываете метод setter:
mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
расширяется до:
[[mainViewController view] setFrame:[[UIScreen mainScreen] applicationFrame]];
В идеале, для будущего доказательства вашего кода вы также должны использовать self.mainViewController
(или [self mainViewController]
) при получении этого значения. В общем, классы гораздо реже имеют важный код в своих методах "getter", чем их "сеттеры", но все же возможно, что доступ непосредственно может нарушить что-то в будущей версии Cocoa Touch.
Ответ 2
ключевое слово self
указывает, что вы используете свойство getter/setter вместо прямого доступа к значению. в случае, если вы позволите автогенератору/сеттеру автоматически сгенерировать, используя синхронизацию, вы должны использовать self в первом примере, потому что объект сохраняется там вместо простого указателя.