我需要释放 xib 资源吗?

Do I need to release xib resources?

提问人:rustyshelf 提问时间:9/15/2008 最后编辑:Bill the Lizardrustyshelf 更新时间:4/13/2012 访问量:9396

问:

如果我有类似 UILabel 链接到 xib 文件的东西,我是否需要在我的视图的 dealloc 上发布它?我问的原因是因为我没有分配它,这让我觉得我也不需要发布它? 例如(在标题中):

IBOutlet UILabel *lblExample;

在实现中:

....
[lblExample setText:@"whatever"];
....

-(void)dealloc{
    [lblExample release];//?????????
}
iPhone Objective-C 可可触摸

评论


答:

0赞 Sören Kuklau 9/15/2008 #1

相关新闻: 了解 Cocoa 的参考计数 / Objective C

评论

1赞 rustyshelf 9/15/2008
@Soeren:我已经看过那篇文章,并了解它的内容。我的问题与在 IB xib 上实例化的对象有关,它没有涵盖。例如:我从来没有真正创建或分配标签,IB的魔力做到了这一切。所以我需要知道的很简单:我需要释放它吗?
0赞 Kendall Helmstetter Gelner 9/15/2008 #2

从某种意义上说,您可以通过在 IB 中创建标签来分配标签。

IB所做的是查看您的IBOutlets以及它们是如何定义的。如果您有一个类变量,IB 将为其分配对某个对象的引用,则 IB 将为您向该对象发送 retain 消息。

如果您使用属性,IB将使用您必须设置值的属性,而不是显式保留该值。因此,您通常会将 IBOutlet 属性标记为 retain:

@property (nonatomic, retain) UILabel *lblExample;

因此,在以太的情况下(无论是否使用属性),您应该在 dealloc 中调用 release。

评论

3赞 mmalc 10/11/2008
这是不正确的。如果你不使用属性(或实现你自己的访问器方法),那么是否应该释放取决于你所处的平台和你的超类是什么。例如,如果从 NSWindowController 继承,则不会发布。
4赞 rustyshelf 9/15/2008 #3

我在 Apple 文档中找到了我想要的东西。简而言之,您可以将对象设置为释放和保留的属性(或者只是@property,@synthesize),但对于诸如 UILabels 之类的内容,您不必这样做:

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000051i-CH4-SW18

0赞 Eric Allam 9/15/2008 #4

任何作为 Nib 主视图的子视图的 IBOutlet 都不需要释放,因为它们将在创建对象时发送自动释放消息。您需要在 dealloc 中释放的唯一 IBOutlet 是顶级对象,如控制器或其他 NSObject。这在上面链接的 Apple 文档中都提到了。

评论

3赞 mmalc 10/10/2008
这实际上是错误的。是否应向顶级对象发送发布消息取决于您使用的平台以及 File's Owner 继承的类。例如,如果它继承自 NSWindowController,则无需释放它们。
35赞 mmalc 10/10/2008 #5

如果遵循现在被认为是最佳实践的做法,则应释放 outlet 属性,因为应该在 set 访问器中保留它们:

@interface MyController : MySuperclass {
    Control *uiElement;
}
@property (nonatomic, retain) IBOutlet Control *uiElement;
@end


@implementation MyController

@synthesize uiElement;

- (void)dealloc {
    [uiElement release];
    [super dealloc];
}
@end

这种方法的优点是,它使内存管理语义明确明了,并且它在所有平台上一致地适用于所有 nib 文件

注意:以下注释仅适用于 3.0 之前的 iOS。在 3.0 及更高版本中,您应该简单地将 viewDidUnload 中的属性值清空。

不过,这里的一个注意事项是,当控制器可能会释放其用户界面并按需动态重新加载它时(例如,如果您有一个视图控制器,它从 nib 文件加载视图,但根据请求(例如在内存压力下)释放它,并期望在再次需要视图时可以重新加载它)。在这种情况下,您需要确保在释放主视图时也放弃任何其他出口的所有权,以便也可以解除分配这些出口。对于 UIViewController,可以通过重写来处理此问题,如下所示:setView:

- (void)setView:(UIView *)newView {
    if (newView == nil) {
        self.uiElement = nil;
    }
    [super setView:aView];
}

不幸的是,这引发了另一个问题。由于 UIViewController 当前使用访问器方法实现其方法(而不是简单地直接释放变量),因此将被调用并响应内存警告...这将导致 中的崩溃。deallocsetView:self.anOutlet = nildeallocdealloc

补救措施是确保出口变量也设置为:nildealloc

- (void)dealloc {
    // release outlets and set variables to nil
    [anOutlet release], anOutlet = nil;
    [super dealloc];
}

评论

0赞 11/24/2010
如果我们有一个 retain 属性,我们难道不能通过简单地说 self.uiElement = nil 来简化它吗?在我们想要释放的所有地方,由于它是一个保留属性,它实际上应该正确释放它,并将其设置为零,没有问题,这是保留属性的优点之一。
1赞 Jesse Rusak 1/15/2011
您通常会在 not in 中执行。而且,如果只调用交易点,那就更清楚了。self.uiElement = nil;viewDidUnloadsetView:self.anOutlet = nil;
2赞 tobyc 2/1/2011
你不应该调用 self.anOutlet = nil;在 dealloc.在 dealloc 中调用访问器是一种不好的做法。
1赞 Wil Shipley 3/19/2011
我完全不同意“在 dealloc 中调用访问器是不好的做法”,我经常这样做,这使代码干净十亿倍。你有这方面的参考吗?
1赞 Chuck 4/3/2011
@Wil Shipley:一些 Apple 文档建议不要使用 init 和 dealloc 方法中的访问器。例如:developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/... — AFAICT,基本上 setter 除了设置变量之外,还可以(在 KVO 下)产生副作用,如果您触发 KVO 通知,您最终可能会告诉人们在解除分配后发送对象消息。
3赞 Wil Shipley 2/20/2009 #6

[anOutlet release], anOutlet = nil;

如果你正确地编写了 setView:,那么部分是完全多余的。

评论

1赞 Wil Shipley 3/19/2011
实际上,据我所知,这在 3.0 及更高版本中发生了变化。我们现在有了 -viewDidUnload,这就是我们发布访问器的地方。
1赞 Shaikh Sonny Aman 2/19/2010 #7

如果您不在 dealloc 上发布它,它会增加内存占用。

在此处查看仪器 ObjectAlloc 图的更多详细信息

0赞 stephen 4/13/2012 #8

如果未将 IBOutlet 设置为属性,而只是将其设置为实例变量,则仍必须释放它。这是因为在 initWithNib 上,内存将分配给所有 IBOutlet。因此,这是您必须释放的特殊情况之一,即使您没有在代码中保留或分配任何内存。