良好实践/不良实践 - 指针和设置值 - Objective C

发布于 2024-10-26 11:55:03 字数 981 浏览 1 评论 0原文

我仍在思考指针。我编写了以下代码,并对它的优点表示怀疑。

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

它有效,但谁能指出为什么我不应该这样做: 我有一个自定义 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 指向同一个对象。这种类型的间接对象设置是否可取?如果没有,处理栏按钮场景的更好方法是什么?

非常感谢, 马特

I'm still getting my head around pointers. I've written the following code, and have my doubts about it's goodness.

I needed my view controller to be able to set a custom title for it's UIBarButtonItem depending on which new view controller it was going to push onto the navigation controller's stack. Rather than having conditional code to check if self.navigationItem.backBarButtonItem existed every time before I attempted to set it's new title (because by default, unless you create it, self.navigationItem.backBarButtonItem is nil), I did this:

It works, but can anyone point out why I shouldn't do this:
I have a custom getter to lazily instantiate a navigation bar back button:

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

}

Now in the rest of the .m file, whenever I want to change the title of the back button (eg before I push a new view controller onto the navigation controller's stack), I simply do:

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

or:

self.myBackButton.title = self.title;

And I believe this works because self.myBackButton and self.navigationItem.backBarButtonItem are pointing to the same object. Is this type of indirect setting of objects advisable? If not, what would be a better way to handing the bar button scenario?

Many Thanks,
Matt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

歌枕肩 2024-11-02 11:55:03

您应该阅读内存管理指南来了解分配,保留,...

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

不需要延迟实例化后退按钮,它只是一小块内存,我假设您总是希望它可见。更好的方法是在 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

You should read Memory Management Guide to learn about alloc, retain, ...

You're allocating back button (= you own it) and you do retain it too (= you own it twice), thus you have to call release twice too.

No need to lazily instantiate back button, it's a small chunk of memory and I assume you do always want it visible. Better way is to do this in init method of your UIViewController.

Correct way is ...

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

... to summarize memory management guide rules ...

  • every method whose name begins with alloc, new, copy or mutableCopy creates an object, which is your (= you take ownership, you have to release it somewhere)
  • if you want to release it (read relinquish ownership), you should call release or autorelease on this object, good practice is to set ivar to nil too
各空 2024-11-02 11:55:03

您可能想将该方法更改为类似的方法。

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

然后,在其他地方(可能在您的 viewDidLoad/appear 中)调用

self.navigationItem.backBarButtonItem= self.myBackButton;

我已将保留更改为自动释放,因为任何带有 init、copy 或 new 的方法都会增加保留计数。如果它不包含 init copy 或 new,它应该返回一个自动释放的实例。

另外,当您将其设置为 backbuttonItem 时,无论如何它都会被保留。

值得注意的是,当通过点表示法访问属性时,您实际上正在经历 setter 和 getter。 ie

self.myBackButton.title =@"title";

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

您几乎应该总是遍历 setter 和 getter 而不是将其作为局部变量访问。即使用

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

you probably want to change that method to something like this.

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

then, somewhere else(probably in your viewDidLoad/appear) call

self.navigationItem.backBarButtonItem= self.myBackButton;

I've changed the retain to autorelease, as any method with init, copy or new will incriment the retain count. if it doesn't contain init copy or new, it should return an autoreleased instance.

also when you set it to the backbuttonItem, it is retained by that anyway.

Its worth noting that when accessing properties through dot notation, you are actually going through the setters and getters. ie

self.myBackButton.title =@"title";

is the same as

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

You should almost always go through the setters and getters rather than accessing it as a local variable. i.e. use

self.myBackButton instead of myBackButton as this will allow you to do any required setup on the way through, and also to know that if any code is accessing it it will be going through that method rather than altering the variable directly.

你的心境我的脸 2024-11-02 11:55:03

是的,您不清楚内存管理规则,但更多的是您的问题:不,不必费心实现此后退按钮访问器,已经有一个后退按钮访问器,它是 self.navigationItem.backBarButtonItem

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

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

因此,无论您想在何处使用 self.myBackButton.title<,请取出该访问器/code> 而是使用 self.navigationItem.backBarButtonItem ,最后确保在必须访问它之前调用的位置(通常是您的 init )对其进行初始化。

Yeah, you're not clear about memory management rules, but more to your question: no, don't bother implementing this back button accessor, there already is a back button accessor and it's self.navigationItem.backBarButtonItem.

This method you've suggested is a lazy accessors, which you use when you have an object that isn't needed until the accessors is called. It hides the details of the object's creation to the callers who don't need to know.

However this situation the object, the button, is needed by the navigation view controller at the right time and should be created where it makes sense to. This is in a view controller, I think the button should be created either in init, loadView, or perhaps viewWillAppear. In this situation the details of the buttons creation should be explicit in whichever one of those location you have it in.

So take out that accessor, wherever you wanted to use self.myBackButton.title instead use self.navigationItem.backBarButtonItem and lastly make sure you initialize it in a place that's called before you ever have to access it (often your init).

镜花水月 2024-11-02 11:55:03

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

Your question boils down to this: What happens to the back button after it was pressed - when the view it controls is released. Check the retain count of your back button in these situations. If it remains stable, you're OK (assuming that no other modules in your program assign different back button instances). Otherwise, you will have to create a new back button each time you need one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文