在框架项目中放置.xib文件的位置在哪里?

15

我花了半天的时间琢磨这个问题,但在网上找不到简单直接的解决方案。

我创建了一个iOS CocoaTouch框架,其中包含一些私有和公共类,所有内容都正常工作。问题在于当我在该框架中添加.xib文件时。

在我的框架内部,我想实例化 .xib 文件,但是我收到的错误信息是:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/dino/Library/Developer/CoreSimulator/Devices/FEDECDC2-D4EA-441E-B53B-329A5B3DFB7A/data/Containers/Bundle/Application/78CEC01F-4C36-4143-A7D6-DDE6CCAC801B/MyApp.app> (loaded)' with name 'NUInAppMessageView''

我听说.xib文件不能包含在静态库中,但我认为它们应该能够在框架内使用。

我的框架目标之前包含了“复制捆绑资源”,当我在框架项目内创建它时,这个 .xib 文件被自动添加进去。

enter image description here

我在几个地方看到过资源应该在一个单独的 .bundle 目标中添加,但是在创建新目标时没有“bundle”选项,并且我认为这来自于旧的静态库时代。

这是我在框架内使用的初始化视图的代码:

NSBundle * frameworkBundle = [NSBundle bundleForClass:[self class]]; // fine (not nil)

NUInAppMessageView *view = [[frameworkBundle loadNibNamed:@"NUInAppMessageView" owner:self options:nil] firstObject]; // <-- CRASH
我尝试将其拆分为更多的方法调用,并发现 Nib 本身正在被创建:
UINib *nib = [UINib nibWithNibName:@"NUInAppMessageView"
                                bundle:frameworkBundle]; // fine (not nil)
NSArray *objects = [nib instantiateWithOwner:self options:nil]; // <-- CRASH

我再也没有什么想法了。 我试过使用项目 Clean,删除派生数据,但它们似乎没有起作用。

我错过了什么?


你的代码和我的唯一明显的区别就是我从主代码中加载了那个nib,而不是从框架代码中加载,但这只是一个意外;这没有任何区别。我只是重写了它,让我从框架代码中加载nib,它也可以正常工作。 - matt
@matt 我打算删除所有内容并创建新的.xib文件。可能是Xcode在缓存设置方面出了问题。谢谢。 - vale4674
抱歉我实际上无法回答这个问题。有时候只是被告知“是的,这应该可以工作,你并不疯狂”会有所帮助。 :) - matt
@matt 至少我现在可以享受周末,然后在星期一解决这个问题 :) - vale4674
3个回答

17

iOS项目中如何将Nib文件放入框架中?

我的回答背景:
我试图导出一些与UITableView相关的实现,并带有打包成.nib文件的UITableViewCell .xib文件。最终它们会变成.nib文件!;-) 我将以下内容作为对这些Nib文件的引用:

[[NSBundle mainBundle] loadNibNamed:customCellID owner:nil options:nil];

Explanation:
但是我的错误在于,我创建了一个静态的Cocoa Touch框架,并尝试在另一个应用程序中使用它。因此,在运行时,MainBundle会变成什么?毫无疑问,我的UITableView实现会尝试在应用程序的主要bundle中查找自定义单元格ID的Nib文件。

Answer:
因此,我修改了我的UITableView实现中上面的代码片段如下:

    NSString *frameworkBundleId = @"com.randika.MyFrameworkBundleIDHere";
    NSBundle *resourcesBundle = [NSBundle bundleWithIdentifier:frameworkBundleId];

    customCell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:customCellID];
    if (customCell == nil) {
       NSArray *nibs = [resourcesBundle loadNibNamed:emptyCellID owner:nil options:nil];
       customCell = [nibs objectAtIndex:0];
    }

而我基于自己的UITableView实现构建的框架再也没有出现上述错误了! :-)

希望这个回答能对某些人有所帮助!

干杯! :-)


3

具有.xib文件的控制器的通用解决方案

public extension UIViewController {

    //** loads instance from right framework bundle, not main bundle as UIViewController.init() does
    private static func genericInstance<T: UIViewController>() -> T {
        return T.init(nibName: String(describing: self), bundle: Bundle(for: self))
    }

    public static func instance() -> Self {
        return genericInstance()
    }
}

用途

YourViewController.instance()

1
更简单的方法是使用self引用bundle。
 let bundle = Bundle(for: type(of: self)) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接