Nib 对象的内存管理

Nib 对象的内存管理,第1张

概述转自http://www.apple.com.cn/developer/iphone/library/documentation/UserExperience/Conceptual/MemoryMgmt/Articles/mmNibObjects.html Nib 对象内存管理 在Cocoa应用程序运行时生命周期中,会有一个或多个nib文件被加载,而且它们所包含的对象会被解压。当不再需要它们时, 转自http://www.apple.com.cn/developer/iphone/library/documentation/UserExperIEnce/Conceptual/MemoryMgmt/Articles/mmNibObjects.HTML Nib 对象的内存管理

在Cocoa应用程序运行时生命周期中,会有一个或多个nib文件被加载,而且它们所包含的对象会被解压。当不再需要它们时,谁来负责释放这些对象取决于您在哪种平台进行开发,而且,如果是在Mac OS X的话,还取决于您的file’s Owner继承自哪个类。

关于nib文件及其内存管理语义的基本讨论,以及与nib相关的术语的定义,比如插座对象,file’s Owner和顶层对象,请参考资源编程指南中的“Nib文件”一节。

插座对象

当一个nib文件被加载且插座对象被建立的时候,如果存取方法(在Mac OS X和iOS上都)存在,则nib加载机制一定会使用存取方法。因此,无论您在哪个平台上进行开发,一般情况下,您都应该使用Objective-C的属性声明功能声明插座对象。

声明插座对象的一般形式应该是:

@property (attributes) IBOutlet UserInterfaceElementClass *anOutlet;

插座对象的行为取决于平台的类型(请参考“Mac OS X”“iOS”),因此,实际的声明会有所不同:

对于Mac OS X,您应该使用:

@property (assign) IBOutlet UserInterfaceElementClass *anOutlet;

对于iOS,您应该使用:

@property (nonatomic,retain) IBOutlet UIUserInterfaceElementClass *anOutlet;

接下来,您应该做的是合成相应的存取方法,或者是根据声明实现这些方法,(在iOS平台)还要在dealloc中释放相应的变量。

如果您使用现代运行时并合成实例变量,这种模式同样适用,因此它能够在所有情况下保持一致性。

Mac OS X

在默认情况下,nib文件的File’s Owner负责释放nib文件中的顶层对象和nib中的对象创建的所有非对象资源。对象图中的根对象的释放会促使所有依赖它的对象也被释放。对应用程序的主nib文件(其中包含应用程序菜单和其他可能的项目)来说,它的“文件所有者”是全局应用程序对象NSApp。然而,当Cocoa应用程序终止时,主nib中的顶层对象不会因为NSApp被回收(请参考“回收对象”)而自动获得dealloc消息。换句话说,即使是在主nib文件中,您也必须管理顶层对象的内存。

应用程序套件提供了一系列功能来帮助您确保nib对象能够被正确地释放:

NSWindow对象(包括面板)有一项isReleaseDWhenClosed属性,如果该属性被设为YES,则窗口会在关闭的时候释放它自己(和它的视图层次中所有相关的对象)。在Interface Builder中,您可以通过勾选检视器的属性面板上的“在关闭时释放”复选框来设置此选项。

如果nib文件的“文件所有者”是一个NSWindowController对象(它是基于文档的应用程序中的文档默认nib—前面介绍过,NSdocument负责管理NSWindowController实例),它会自动销毁它所管理的窗口。

因此,在一般情况下,您负责释放nib文件中的顶层对象。但实际上,如果您的nib文件的所有者是一个NSWindowController实例,则它会为您释放顶层对象。如果您的某个对象加载了nib本身(而且它的所有者不是NSWindowController实例),则您可以为每一个顶层对象定义插座对象,以便您可以在适当的时候使用这些引用释放它们。如果您不希望为所有的顶层对象定义插座对象,那么您可以使用NSNib类的instantiateNibWithOwner:topLevelObjects:方法来获得一个包含nib文件顶层对象的数组。

当您考虑到应用程序的各种类型时,销毁nib对象的责任问题就变得更清晰了。大多数Cocoa应用程序归属于两类:单一窗口应用程序和基于文档的应用程序。在这两种情况下,系统会在一定程度上为您自动处理nib对象的内存管理。在单一窗口应用程序中,主nib文件中的对象在应用程序的整个运行周期内持续存在,并在应用程序终止时被释放;但是,系统并不保证在应用程序终止时自动地对主nib文件中的对象调用dealloc。在基于文档的应用程序中,每一个文档窗口都由一个NSWindowController对象管理,该对象处理文档nib文件的内存管理。

有些应用程序可能具有更复杂的nib文件和顶层对象的分布。例如,应用程序可能有多个nib文件,并带有多个窗口控制器,可加载的面板和检视器。但是,在大多数情况下,如果您使用NSWindowController对象来管理窗口和面板,或者如果您设置了“在关闭时释放”这一窗口属性,那么系统会为您自动处理大部分的内存管理。如果您决定不使用窗口控制器,也不想设置“在关闭时释放”属性,则您应该在窗口关闭时显式地释放您的nib文件的窗口和其他顶层对象。此外,如果您的应用程序使用检视器面板,那么(在延迟加载之后)该面板通常应该在整个应用程序生命周期内持续存在—没有必要销毁检视器和它的资源。

iOS 顶层对象

当nib文件中的对象被创建时,它们的保留计数为1,而且随后它们会被自动释放。由于重建了对象层次结构,UIKit会使用setValue:forKey:重新建立对象之间的连接,setValue:forKey:使用现有的setter方法,如果没有setter方法可用,那么它会默认保留这个对象。这就意味着(假设您遵循“插座对象”中所示的模式)具有插座对象的任何对象都保持有效。但是,如果存在您没有存储在插座对象中的顶层对象,则您必须保留loadNibNamed:owner:options:方法返回的数组或数组中的对象,以防止这些对象过早地被释放。.

内存警告

当视图控制器收到内存警告(didReceiveMemoryWarning)的时候,它应该释放那些当前不需要的,和那些如果有需要可以稍后重新创建的资源的所有权。其中一种资源就是视图控制器的视图本身。如果它没有父视图,则该视图应该被销毁(在它的dIDReceiveMemoryWarning实现中,UIVIEwController调用[self setVIEw:nil])。

但是,由于nib文件中的元素的插座对象通常会被保留(见“插座对象”),因此,即使主视图被销毁,如果没有采取任何进一步的行动,插座对象也不会被销毁。这并不是其本身的问题—如果当主视图被重新载入时,它们只是被简单地替换掉—但这确实意味着,dIDReceiveMemoryWarning的效果被削弱了。为了确保您正确地释放插座对象的所有权,在您的自定义视图控制器类中,您可以实现viewDidUnload来调用您的存取方法,以便将插座对象设置为nil

- (voID)vIEwDIDUnload { self.anOutlet = nil; [super vIEwDIDUnload];}

注意:在iOS 3.0版本之前,vIEwDIDUnload方法是不可用的。相反,您应该在setVIEw:中将插座对象设置为nil,正如该例所示:

- (voID)setVIEw:(UIVIEw *)aVIEw { if (!aVIEw) { // VIEw is being set to nil. // Set outlets to nil,e.g. self.anOutlet = nil; } // Invoke super's implementation last. [super setVIEw:aVIEw];}
此外,由于 UIVIEwController中的 dealloc的一个实现细节,您还应该在 dealloc中将插座对象变量设置为 nil

- (voID)dealloc { // Release outlets and set outlet variables to nil. [anOutlet release],anOutlet = nil; [super dealloc]; } 总结

以上是内存溢出为你收集整理的Nib 对象的内存管理全部内容,希望文章能够帮你解决Nib 对象的内存管理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1055184.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存