良好做法/不良做法 - 指针和设定值 - 目标C.

时间:2011-03-24 19:08:16

标签: iphone objective-c pointers uinavigationcontroller uibarbuttonitem

我仍然专注于指针。我写了下面的代码,并对我的好处表示怀疑。

我需要我的视图控制器才能为它的UIBarButtonItem设置自定义标题,具体取决于它将推送到导航控制器堆栈的新视图控制器。在我尝试设置它的新标题之前,每次都检查self.navigationItem.backBarButtonItem是否存在条件代码(因为默认情况下,除非你创建它,self.navigationItem.backBarButtonItem是nil),我做了这个:

它有效,但任何人都可以指出为什么我不应该这样做: 我有一个自定义的getter懒惰实例化导航栏后退按钮:

- (UIBarButtonItem *)myBackButton {
if (!myBackButton) {
    myBackButton =  [[[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:nil] retain];
    self.navigationItem.backBarButtonItem = myBackButton;
}
return myBackButton;

}

现在在.m文件的其余部分,每当我想要更改后退按钮的标题时(例如,在我将新视图控制器推到导航控制器的堆栈之前),我只是这样做:

self.myBackButton.title = @"Some Custom Title";

或:

self.myBackButton.title = self.title;

我相信这是有效的,因为self.myBackButton和self.navigationItem.backBarButtonItem指向同一个对象。这种对象的间接设置是否可取?如果没有,那么处理条形按钮场景的更好方法是什么?

非常感谢, 马特

4 个答案:

答案 0 :(得分:2)

您应该阅读“内存管理指南”以了解alloc,retain,...

你正在分配后退按钮(=你拥有它)并且你也保留它(=你拥有它两次),因此你也必须两次调用释放。

不需要懒惰地实例化后退按钮,这是一小块内存,我认为你总是希望它可见。更好的方法是在UIViewController的init方法中执行此操作。

正确的方法是......

self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];

...总结内存管理指南规则......

  • 每个名称以alloc,new,copy或mutableCopy开头的方法都会创建一个对象,这是你的(=你取得所有权,你必须在某处释放它)
  • 如果你想发布它(读取放弃所有权),你应该在这个对象上调用release或autorelease,好的做法是将ivar设置为nil

答案 1 :(得分:1)

您可能希望将该方法更改为此类。

- (UIBarButtonItem *)myBackButton {
    if (!myBackButton) {
        myBackButton =  [[[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
    }
return myBackButton;
}

然后,在其他地方(可能在你的viewDidLoad /中出现)调用

self.navigationItem.backBarButtonItem= self.myBackButton;

我已将retain更改为autorelease,因为任何使用init,copy或new的方法都会导致保留计数。如果它不包含init copy或new,它应该返回一个自动释放的实例。

当你将它设置为backbuttonItem时,无论如何都会保留它。

值得注意的是,当通过点表示法访问属性时,您实际上是通过setter和getters。即

self.myBackButton.title =@"title";

相同
[[self myBackButton] setTitle:@"title"];

你应该几乎总是通过setter和getter而不是作为局部变量访问它。即使用

self.myBackButton而不是myBackButton,因为这将允许您在通过时进行任何所需的设置,并且还知道如果任何代码正在访问它,它将通过该方法而不是直接更改变量。 / p>

答案 2 :(得分:0)

是的,你不清楚内存管理规则,但更多的是你的问题:不,不要打扰实现这个后退按钮访问器,已经有一个后退按钮访问器,它是self.navigationItem.backBarButtonItem

您建议使用的这种方法是一个惰性访问器,当您在调用访问器之前拥有一个不需要的对象时,可以使用它。它将对象创建的细节隐藏给不需要知道的调用者。

然而,在这种情况下,导航视图控制器在正确的时间需要对象,按钮,并且应该在有意义的地方创建。这是在视图控制器中,我认为应该在init,loadView或viewWillAppear中创建按钮。在这种情况下,按钮创建的详细信息应该显示在您拥有它的任何一个位置。

所以取出那个访问者,无论你想在哪里使用self.myBackButton.title而不是self.navigationItem.backBarButtonItem,最后确保在你必须访问它之前在一个被调用的地方初始化它(通常是你的init)

答案 3 :(得分:-3)

您的问题归结为:按下后退按钮会发生什么 - 当它控制的视图被释放时。在这些情况下检查后退按钮的保留计数。如果它保持稳定,你就可以了(假设你的程序中没有其他模块分配不同的后退按钮实例)。否则,每次需要时都需要创建一个新的后退按钮。