从 iOS 包中加载 Nib 文件的更快方法?
Posted
技术标签:
【中文标题】从 iOS 包中加载 Nib 文件的更快方法?【英文标题】:Faster way to load Nib file from a bundle in iOS? 【发布时间】:2012-10-24 20:54:19 【问题描述】:我有一个应用程序,它使用一组自定义“控件”,这些控件是使用类似于以下方法从 Xib 文件按需加载的:
NSArray * topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"AudioPlayer" owner:self options:nil];
InteractiveMovieView *newAudio = [topLevelObjects objectAtIndex:0];
这种方法效果很好,除非同时加载多个控件(在应用程序的一个“页面”上有效)。
每次从包中加载显然效率低下,但我找不到另一种方法来解决这个问题。我曾尝试将笔尖加载到 copy
属性中一次,并根据需要返回以供重复使用,但这不起作用,因为返回的副本绝不是空白笔尖的“干净”副本。
我希望这是有道理的,感谢所有帮助。
【问题讨论】:
【参考方案1】:听起来您正在寻找UINib
类。来自文档:
只要您的应用程序需要重复实例化相同的 nib 数据,就应该使用
UINib
对象。例如,如果您的表格视图使用 nib 文件来实例化表格视图单元格,则将 nib 缓存在UINib
对象中可以显着提高性能。
【讨论】:
你能解释一下为什么 [UINib nibWithNibName:bundle:] 可以提高性能吗?我认为它只是创建了一个指向 Nib 文件的 UINib 对象。繁重的工作在 [nib instantidateWithOwner:options:] 中,它确实取消了 nib 的归档(在我看来,这个操作要重得多) @entropy 您的陈述与文档相矛盾。 @nielsbot 是的,这肯定是矛盾的,但你不和我一样吗?人们说这很贵,那很贵,......没有理由:( 我认为 Apple 知道他们的代码是如何工作的,而且他们不会无缘无故地将其写在文档中。如果您有疑问,您应该对其进行分析。UINib
缓存来自 nib 的 XML,因此不必每次都将其加载到内存中。虽然所有的取消归档都发生在 instantiateWithowner:options
期间,因此使用 UINib
不会看到巨大的性能优势,除非 nib 太大以至于加载 xml 需要大量时间。【参考方案2】:
按照 Rob 的建议,您可以执行以下操作:
@implmentation InteractiveMovieView (NibFactory)
+(id)movieView
static UINib * __nib ;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
__nib = [ UINib nibWithNibName:@"AudioPlayer" bundle:nil ] ;
);
InteractiveMovieView * view = [ __nib instantiateWithOwner:nil options:nil ][0] ;
return view ;
@end
【讨论】:
几乎所有繁重的工作都发生在通过instantiateWithOwner:options
取消归档视图的过程中。创建静态笔尖不会带来任何性能提升。
如果我理解@Rob 引用的文档,应该缓存UINib
对象,不是吗?
文档的措辞有些混乱。它表示UINib
对象负责缓存,而不是你应该缓存UINib
。
查看instantiateWithOwner:options
的文档,了解繁重的工作发生在哪里:解压缩并实例化接收器的 nib 文件的内存内容,创建一个独特的对象树和一组***对象。 据我所知,通过仪器进行测试,使用 UINib
与 loadNibNamed
在性能方面几乎没有区别。
据我所知确实 缓存了笔尖的数据——XML 本身。但是取消归档和实例化内存中的内容比加载 nib 的 xml 贵几个数量级。所以,是的,使用UINib
肯定会更好,但实际上它几乎没有什么区别,除非你有一个带有多个根对象的巨大 nib,它比典型的要大。以上是关于从 iOS 包中加载 Nib 文件的更快方法?的主要内容,如果未能解决你的问题,请参考以下文章
iOS 10:致命异常:NSInternalInconsistencyException 无法在包中加载 NIB