如果我不保留IBOutlet会怎样? [英] What happens if I don't retain IBOutlet?

查看:97
本文介绍了如果我不保留IBOutlet会怎样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我这样做:

@interface RegisterController : UIViewController <UITextFieldDelegate>
{
    IBOutlet UITextField *usernameField;
}

而不是:

@interface RegisterController : UIViewController <UITextFieldDelegate>
{
    UITextField *usernameField;
}
@property (nonatomic, retain) IBOutlet UITextField *usernameField;

会发生什么不好的事吗?我知道在第二种情况下,该字段被保留,但由于笔尖拥有该字段,这是否会有所不同?没有保留,这个领域会消失吗?在什么情况下?第一种情况下的代码工作,想知道这是否是内存管理方面的问题。

Will something bad happen? I know in the second case, the field is retained, but does this make a different since the nib owns the field? Will the field go away without the retain? and under what circumstances? The code in the first case works, was wondering whether this is an issue or not in terms of memory management.

推荐答案

它是为了清晰和一致,建议您为所有IBOutlet声明属性。
详细信息详见内存管理编程指南。基本要点是,当您的NIB对象被取消归档时,nib加载代码将通过setValue:forKey:来设置所有IBOutlet。当您在属性上声明内存管理行为时,对于发生的事情并不神秘。如果视图被卸载,但是您使用了一个声明为retain的属性,那么您仍然可以获得对文本字段的有效引用。

It is recommended you declare properties for all of your IBOutlets for clarity and consistency. The details are spelled out in the Memory Management Programming Guide. The basic gist is, when your NIB objects are unarchived, the nib loading code will go through and set all of the IBOutlets using setValue:forKey:. When you declare the memory management behavior on the property, there is no mystery as to what is going on. If the view gets unloaded, but you used a property that was declared as retain, you've still got a valid reference to your textfield.

也许更具体的例子是有用的说明为什么你应该使用保留属性:

Perhaps a more concrete example would be useful to indicate why you should use a retaining property:

我将对你工作的背景做一些假设 - 我会假设上面的UITextField是由UIViewController控制的另一个视图的子视图。我将假设在某些时候,视图不在屏幕上(可能是在UINavigationController的上下文中使用),并且在某些时候你的应用程序会收到内存警告。

I'm going to make some assumptions about the context in which you're working--I'll assume the UITextField above is a subview of another view that is controlled by a UIViewController. I will assume that at some point, the the view is off the screen (perhaps it is used in the context of a UINavigationController), and that at some point your application gets a memory warning.

因此,假设您的UIViewController子类需要访问其视图以在屏幕上显示它。
此时,将加载nib文件,并使用setValue:forKey:由nib加载代码设置每个IBOutlet属性。这里要注意的重要事项是将设置为UIViewController的view属性的顶级视图(将保留此顶级视图)和UITextField,它们也将被保留。如果只是设置它,它将通过nib加载代码保留它,否则属性将保留它。 UITextField也将是顶级UIView的子视图,因此它将在顶层视图的子视图数组中有一个额外的保留,所以此时文本字段已被保留两次。

So lets say your UIViewController subclass needs to access its view to display it on screen. At this point, the nib file will be loaded and each IBOutlet properties will be set by the nib loading code using setValue:forKey:. The important ones to note here are the top level view that will be set to the UIViewController's view property, (which will retain this top level view) and your UITextField, which will also be retained. If it is simply set, it'll have a retain put on it by the nib loading code, otherwise the property will have retained it. The UITextField will also be a subview of the top level UIView, so it will have an additional retain on it, being in the subviews array of the top level view, so at this point the text field has been retained twice.

此时,如果您想以编程方式切换文本字段,则可以这样做。使用该属性可以使内存管理更加清晰;您只需使用新的自动释放文本字段设置该属性。如果您尚未使用该属性,则必须记住将其释放,并可选择保留新属性。在这一点上,对于拥有这个新文本字段的人来说有点模糊,因为内存管理语义不包含在setter中。

At this point if you wanted to switch out the text field programmatically, you could do so. Using the property makes memory management more clear here; you just set the property with a new autoreleased text field. If you had not used the property, you must remember to release it, and optionally retain the new one. At this point it is somewhat ambiguous as to whom owns this new text field, because the memory management semantics are not contained within the setter.

现在让我们说一个不同的视图控制器被推到UINavigation Controller的堆栈上,因此该视图不再位于前台。在内存警告的情况下,将卸载此屏幕外视图控制器的视图。此时,顶级UIView的view属性将被清除,它将被释放并释放。

Now let's say a different view controller is pushed on the UINavigation Controller's stack, so that this view is no longer in the foreground. In the case of a memory warning, the view of this offscreen view controller will be unloaded. At this point, the view property of the top level UIView will be nulled out, it will be released and deallocated.

因为UITextField被设置为保留的属性,所以UITextField没有被释放,因为它本身只保留了它的子视图数组。顶级视图。

Because the UITextField was set as a property that was retained, the UITextField is not deallocated, as it would have been had its only retain been that of the subviews array of the top level view.

如果没有通过属性设置UITextField的实例变量,它也会出现,因为nib加载代码保留了它设置实例变量。

If instead the instance variable for the UITextField not been set via a property, it'd also be around, because the nib loading code had retained it when setting the instance variable.

有一点值得注意的是,因为UITextField还通过属性保留,所以你可能不想保留它。记忆警告。因此,您应该在 - [UIViewController viewDidUnload]方法中清零该属性。这将取消UITextField上的最终版本并按预期取消分配。如果使用该属性,则必须记住明确释放它。虽然这两个动作在功能上是等价的,但意图却不同。

One interesting point this highlights is that because the UITextField is additionally retained through the property, you'll likely not want to keep it around in case of a memory warning. For this reason you should nil-out the property in the -[UIViewController viewDidUnload] method. This will get rid of the final release on the UITextField and deallocate it as intended. If using the property, you must remember to release it explicitly. While these two actions are functionally equivalent, the intent is different.

如果不是交换文本字段,而是选择将其从视图中删除,您可能已经从视图层次结构中删除它并将属性设置为nil,或者释放文本字段。虽然在这种情况下可以编写正确的程序,但很容易在viewDidUnload方法中产生过度释放文本字段的错误。过度释放对象是导致崩溃的错误;将已经为零的属性再次设置为nil不是。

If instead of swapping out the text field, you chose to remove it from the view, you might have already removed it from the view hierarchy and set the property to nil, or released the text field. While it is possible to write a correct program in this case, its easy to make the error of over-releasing the text field in the viewDidUnload method. Over-releasing an object is a crash-inducing error; setting a property that is already nil again to nil is not.

我的描述可能过于冗长,但我不想在方案中遗漏任何细节。简单地遵循这些指南将有助于避免在遇到更复杂的情况时出现问题。

My description may have been overly verbose, but I didn't want to leave out any details in the scenario. Simply following the guidelines will help avoid problems as you encounter more complex situations.

另外值得注意的是桌面上的Mac OS X上的内存管理行为不同。在桌面上,在没有setter的情况下设置IBOutlet不会保留实例变量;但如果可用的话,再次使用setter。

It is additionally worth noting that the memory management behavior differs on Mac OS X on the desktop. On the desktop, setting an IBOutlet without a setter does not retain the instance variable; but again uses the setter if available.

这篇关于如果我不保留IBOutlet会怎样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆