如果你有一个IBOutlet,但不是一个财产,是否保留? [英] If you have an IBOutlet, but not a property, is it retained or not?

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

问题描述

我发现有关此问题的文档不清楚:



假设您使用的是iOS(不是Mac的情况,不需要提及差异)。说它是严格的4.0+(无需提及旧操作系统的差异)。假设我们正在自动加载NIB。



假设你有一个UIViewController,BigView。假设NIB文件中有十多个所谓的顶级项目...可以是自定义控件,图片或其他任何内容。



说你是肯定会明确地创建,然后在应用程序的运行期间摆脱BigView多次。所以:



对于NIB中的其中一个顶级项目,有三种可能性



(1)你没有任何类型的IBOutlet。



(2)你有一个连接的IBOutlet - 一个属性。



(3)你有一个连接的IBOutlet属性(为了避免混淆,我们会说一个retain属性)。



那么当BigView被发布时,该项目会发生什么变化?



在(3)您必须明确发布。如果你不,它会挂在视图不见了。没有问题。



在(1)的情况下,我假设(但任何人都可以确认?



在(2)的情况下,不清楚会发生什么......



查看众所周知的参考链接: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html 这是非常dubious:



在iOS中,nib加载代码使用setValue:forKey:方法重新连接每个插座,该方法同样寻找一个合适的访问器方法,如果这不是一个故事,当我们失败时...] [



请查看此文档: http:// developer .apple.com / library / mac /#documentation / Cocoa / Conceptual / LoadingResources / CocoaNibs / CocoaNibs.html 并向下滚动到Nib对象保留



所以...



创建nib文件中的对象,保留计数为1,然后自动释放 p>

但请稍等!阅读几个字...



但是,...使用可用的setter方法或如果没有setter方法默认保留对象



他们在说什么?



这是否意味着如果没有setter ,但没有属性),它是 AGAIN RETAINED(除了他们在前面的子句中提到的保留)---或者,他们只是重复自己,即保留对象默认情况下是相同的保留他们之前说的(保留计数为1创建,然后自动释放)。





确实 - 如果任何人确实知道这个问题的答案...... 你怎么知道的?!?您问过DTS,还是通过测试,或?



再次 - 如果您有一个IBOutlet,但不是属性,连接到一个顶级对象。你负责发布它吗?



在这种情况下,只有在情况(1)中,绝对是这样的情况:在BigView离开时发布?我肯定会认为这是case,但谁知道?



问题是如果你使用IBOutlet iVar,但不是一个属性...

我愚蠢的从来没有想过这个/假设太多,有人有决定性的答案吗? Cheers !!






对于记录我已经做了一个测试项目。



事实上(令我惊讶的是)将IB元素连接到IBOutlet的行为实际上显然添加了一个retain





因此,这是一个非常简单的方法。答案。



我将发布演示项目。我也指示任何读者到Jonah的答案,下面这些解释正确地解释了setValue的行为:forKey:Cheers

解决方案

什么导致这么多的混乱,我认为Nib对象保留文档解释发生了什么。让我们分解一下,看看会发生什么:


创建nib文件中的对象,保留计数为1,然后自动释放。




  ClassLoadedFromNib * loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease]; 







对象层次结构,然而,UIKit使用setValue:forKey:方法重新建立对象之间的连接,




  [filesOwner setValue:loadedObject forKey:nameOfIBOutlet]; 







可用的setter方法,或如果没有setter方法可用,则默认保留对象。


在iOS中 -setValue:forKey:的默认行为大致

  // lazy pseudocode 
if([self responsesToSelector:@selector(@setKeyName:)]){
[self setKeyName:value];
}
else {
object_setIvar(self,_keyName,[value retain]);
}

有关详细信息,请参阅键值编程指南。除非文件的所有者对象覆盖 -setValue:forKey:(或 + accessInstanceVariablesDirectly -setValue :forUndefinedKey:)期望对象所有权如上所述进行管理。







如果为nib文件对象定义插口,则应始终定义setter方法(或声明的属性)访问该出口。出口的Setter方法应该保留它们的值,并且包含顶级对象的出口的setter方法必须保留它们的值以防止它们被释放。


允许nib加载将ivar直接设置到外部保留的对象是混乱的。不要这样做。为您的插座提供setter方法,以便已装载对象的所有权清楚。







您不会将顶层对象存储在插座中,您必须保留由loadNibNamed:owner:options:方法返回的数组或数组中的对象,以防止这些对象过早释放。


未连接到插座的对象已自动释放。保留它们或从-loadNibNamed:owner:options返回的数组:如果以后尝试访问它们。


I find the documentation on this issue to be unclear:

Say you are working with iOS (NOT the Mac case, no need to mention the differences). Say it is strictly 4.0+ (no need to mention differences in old OS). Say we are loading the NIB strictly automatically.

Say you have a UIViewController, BigView. Say there are a dozen so-called "top-level" items in the NIB file...could be custom controls, images, or anything else.

Say you are definitely going to explicitly create and then get rid of BigView a number of times during the app's run. So:

For one of these top-level items in the NIB, there are three possibilities:

(1) You do not have any sort of IBOutlet for it, at all.

(2) You do have a connected IBOutlet - but not a property.

(3) You do have a connected IBOutlet property (to avoid confusion, we'll say a retain property).

So what happens to the item when BigView is released?

In the case of (3) it seems clear that you must release explicitly. If you do not, it will hang around after the view is gone. No problem.

In the case of (1) I assume (but can anyone actually confirm?) that the item will be released when BigView is gone.

In the case of (2) it's not clear what happens.......

Looking at the well-known reference link: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html it is very dubious:

"In iOS, the nib-loading code uses the setValue:forKey: method to reconnect each outlet. That method similarly looks for an appropriate accessor method and [SO WHAT HAPPENS IF THERE ISN'T ONE?? TELL US APPLE...] falls back on other means when that fails...[GOOD GRIEF!]"

And check out this documentation: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html and scroll down to "Nib Object Retention"

So ...

"Objects in the nib file are created with a retain count of 1 and then autoreleased" Fantastic..

But wait! Read on a few words...

however, ... which uses the available setter method or retains the object by default if no setter method is available

What are they talking about?

Do they mean that if no setter is available (ivar, but no property), that it is AGAIN RETAINED (other than the "retain" they just mention in the previous clause) --- or, are they just repeating themselves, i.e. the "retains the object by default" is the same "retain" they were talking about immediately previously ("created with a retain count of 1 and then autoreleased").

And why would they even mention the autorelease if that's not what happens?

Indeed -- if anyone actually specifically knows the answer to this question ...... how do you know?!? Did you ask DTS, or through testing, or? I suggest, the key documentation (just pasted in) is aggressively unclear.

Again - if you have an IBOutlet, but not a property, connected to a "top-level" object .. are you responsible for releasing it? Is it retained? in that situation?

For that matter .... merely in situation (1) is it absolutely the case that the thingy will be released when BigView goes away? I would certainly assume this is the case, but who knows?

The question is what happens if you DO use an IBOutlet iVar, but NOT a property...

I've foolishly never thought about this before / assumed too much, does anyone have the decisive answer? Cheers!!


For the record I have made a test project.

In fact (surprisingly to me) the mere act of connecting an IB element to an IBOutlet in fact apparently adds one retain.

(I can only assume from the shoddy docu, in that situation you get specifically: Retain, Autorelease, Retain - leading to one retain on balance.)

So, that's the answer.

I will post the demo project. I also direct any readers to Jonah's answer below which flawlessly explains the behavior of setValue:forKey: Cheers

解决方案

I don't see what causes so much confusion, I think the "Nib Object Retention" documentation explains exactly what happens. Let's break it down and walk through what happens:

Objects in the nib file are created with a retain count of 1 and then autoreleased.

ClassLoadedFromNib *loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease];


As it rebuilds the object hierarchy, however, UIKit reestablishes connections between the objects using the setValue:forKey: method,

[filesOwner setValue:loadedObject forKey:nameOfIBOutlet];


which uses the available setter method or retains the object by default if no setter method is available.

The default behavior of -setValue:forKey: in iOS is roughly

//lazy pseudocode
if ([self respondsToSelector:@selector(@"setKeyName:")]) {
  [self setKeyName:value];
}
else {
  object_setIvar(self, _keyName, [value retain]);
}

See the key-value programming guide for even more detail. Unless your file's owner object overrides -setValue:forKey: (or +accessInstanceVariablesDirectly and -setValue:forUndefinedKey: ) expect object ownership to be managed as above.


If you define outlets for nib-file objects, you should always define a setter method (or declared property) for accessing that outlet. Setter methods for outlets should retain their values, and setter methods for outlets containing top-level objects must retain their values to prevent them from being deallocated.

Allowing nib loading to set ivar directly to externally retained objects is confusing. Don't do that. Provide setter methods for your outlets so the ownership of the loaded object is clear.


If you do not store the top-level objects in outlets, you must retain either the array returned by the loadNibNamed:owner:options: method or the objects inside the array to prevent those objects from being released prematurely.

Objects not connected to outlets have been autoreleased. Retain them or the array returned from -loadNibNamed:owner:options: if you are going to try to access them later.

这篇关于如果你有一个IBOutlet,但不是一个财产,是否保留?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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