NSBundle 加载一个 NSViewController

Posted

技术标签:

【中文标题】NSBundle 加载一个 NSViewController【英文标题】:NSBundle loading a NSViewController 【发布时间】:2010-05-27 14:22:45 【问题描述】:

我正在研究一个可以上传包含 NSViewController 的自定义 NSBundle 的项目。在我的主程序中,我有这段代码来处理加载后的包......

id principalClass = [loadedBundle principalClass];
id instance = [[principalClass alloc] init];
[localLabel setStringValue:[instance name]];
NSView *incomingView = [[instance viewController] view];
[localView addSubview:incomingView];
[localView display];

包中的主体类init方法看起来像这样......

-(id) init 
    if(self = [super init])
        name = @"My Plugin";
        viewController = [[ViewController alloc] initWithNibName:@"View" bundle:nil];
    
    return self;

View.nib 是位于 bundles 项目中的一个 nib。但是每当我加载捆绑包时,我都会收到此错误...

2010-05-27 09:11:18.423 PluginLoader[45032:a0f] 找不到 nib 命名:在包路径中查看:(null) 2010-05-27 09:11:18.424 PluginLoader[45032:a0f] -[NSViewController loadView] 无法加载“视图”笔尖。

我知道我已经把所有东西都连接好了,因为[label setStringValue:[instance name]]; 行正确设置了标签文本。另外,如果我将包中的所有类都加载到我的主应用程序项目中,一切都会按预期工作。关于如何在我的包中正确引用“视图”有什么想法吗?

谢谢!

【问题讨论】:

【参考方案1】:

init 方法中,您不应将nil 传递给bundle 参数。根据UIViewController 文档,传递nil 将在主包(应用程序的包)中查找NIB 文件,这不是您想要的。

您可以通过使用这样的专用初始化程序来解决问题:

- (id) initWithBundle:(NSBundle *)bundle 
    if(self = [super init])
        name = @"My Plugin";
        viewController = [[ViewController alloc] initWithNibName:@"View" bundle:bundle];
    
    return self;

并按如下方式使用:

Class principalClass = [loadedBundle principalClass];
id instance = [[principalClass alloc] initWithBundle:loadedBundle];

【讨论】:

[loadedBundle principalClass] 返回类型 Class,而不是 id。出于可读性原因,我可能会为 principalClass 变量使用 Class 类型。【参考方案2】:

“View.xib 是一个 nib”?它要么是xib,要么是nib。 xib 不是笔尖。 xib 文件只能在界面构建器中使用,在部署应用程序中必须将它们转换为 nib 文件。这就是 ibtool 正在做的事情。 Xcode 不会简单地复制您的 xib 文件,它会通过 ibtool 运行它们,将它们转换为 nib 文件,然后放置到 Resources 文件夹中。

【讨论】:

xib 是一个 nib,只是 XML 格式。 Interface builder 可以与 xib 或 nib 一起使用,但 xib 更便于开发,因为它们与 SCM 工具配合得更好。 @dreamlax:Apple 的文档非常清楚地表明,xib 文件不打算部署。即使在创建调试版本时,您也应该在复制阶段将 xib 转换为 nib 文件。 Apple 不保证任何可以处理 nib 文件的方法/函数都可以同样处理 xib 文件。考虑像 PDF(矢量图形、文本和位图)这样的 xib 文件和像 PNG 文件(仅限位图)这样的 nib 文件。并非所有可以处理 PNG 图像的图像函数都可以处理 PDF 文档。 您将 nib/xib 文件格式 与 nib 文件混淆了。见this doc。 xib 文件格式仍然代表一个 nib 文件。 nib 文件有两种格式,xib 和 nib。在引入 xib 之前(仅出于更好的 SCM 支持目的),nib 文件具有一种格式,即 nib 文件格式。来自链接:“xib 文件格式表示 nib 文件对象图的扁平存档。” @dreamlax:在您的链接之后,您不清楚以下句子的哪一部分:“这种类型的文件具有 .xib 扩展名,只能在 Xcode 和 Interface Builder 环境中使用. 您无法在运行时从您的应用程序代码加载 .xib 文件。”? “您无法加载”几乎可以备份我之前所说的所有内容。 @Mecki:阅读整个文档:“Interface Builder 文档是扩展名为 .nib 或 .xib 的文件。这些文档通常称为 nib 文件。”扩展名表示 nib 文件 [对象图] 的底层表示。

以上是关于NSBundle 加载一个 NSViewController的主要内容,如果未能解决你的问题,请参考以下文章

Retina 图形未从 NSBundle 加载

NSBundle - (尚未加载)错误

使用 NSBundle 加载我的资源

NSBundle 未加载 - 目标 C

无法在 iphone 单元测试中从 NSBundle 加载文件

NSBundle的加载和卸载