Objective-C - 何时使用'self'

Joe*_*Joe 49 iphone cocoa-touch objective-c

这是来自Apple的iPhone"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];

}
Run Code Online (Sandbox Code Playgroud)

mainViewController被分配到aController时,self被指定的关键字:

 self.mainViewController = aController;
Run Code Online (Sandbox Code Playgroud)

但是,mainViewController设置框架时,self不需要关键字:

 mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
Run Code Online (Sandbox Code Playgroud)

如果我self从第一个示例中删除关键字,程序将崩溃并显示以下消息:

objc[1296]: FREED(id): message view sent to freed object=0x3b122d0
Run Code Online (Sandbox Code Playgroud)

如果我将self关键字添加到第二个示例,程序运行正常.

任何人都可以解释为什么self在第一种情况下需要而不是第二种情况?我假设在两种情况下mainViewController都引用相同的实例变量.

Tob*_*hen 49

使用self会导致调用此变量的类"setter",而不是直接更改ivar.

self.mainViewController = aController;
Run Code Online (Sandbox Code Playgroud)

相当于:

[self setMainViewController:aController];
Run Code Online (Sandbox Code Playgroud)

另一方面:

mainViewController = aController;
Run Code Online (Sandbox Code Playgroud)

只是mainViewController直接更改实例变量,跳过可能构建到UIApplication setMainViewController方法中的任何其他代码,例如释放旧对象,保留新对象,更新内部变量等等.

在您访问框架的情况下,您仍然在调用setter方法:

mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
Run Code Online (Sandbox Code Playgroud)

扩展为:

[[mainViewController view] setFrame:[[UIScreen mainScreen] applicationFrame]];
Run Code Online (Sandbox Code Playgroud)

理想情况下,为了将来验证您的代码,您也应该在检索此值时使用self.mainViewController(或[self mainViewController]).一般来说,类在他们的"getter"方法中拥有重要代码的可能性要小于"setter",但是直接访问仍然可能会在未来版本的Cocoa Touch中破坏某些东西.

  • 你应该总是使用self,除了getter和setter方法本身(如果你自己编写).这样你的对象保留就会自动处理.您还可以提供自定义代码来执行此操作,例如验证iVar或保持从不存在.在getter和setter方法之外,很少有任何理由直接访问iVar.虽然,很多人通常会出错或懒惰. (5认同)
  • 我认为至少还有一个例外,你可以直接访问ivar:在dealloc中.除此之外,我想你应该总是将自己与吸气者和二传手一起使用. (3认同)

Rus*_*sso 11

self关键字表明您正在使用属性的getter/setter方法,而不是直接访问值.如果您使用同步自动生成getter/setter,则必须在第一个示例中使用self,因为该对象保留在那里而不是简单地指针指定.

  • self是这个指针,类似于c ++.它包含类的地址. (4认同)