用 CocoaPods 集成 Swift 代码引入的 NSBundle 问题

适用情况

  1. iOS 8.0 以上支持

  2. 通过 CocoaPods 引入 Swift 编写的库

问题背景

CocoaPods 在 0.36.0 版本开始,支持了 framework 和 Swift,由于 Swift 只支持 framework,所以在用 CocoaPods 集成 Swift 代码时,必须要在 Podfile 文件里添加 use_frameworks!,才能正确集成 Swift 项目(子 Pod )。但是由于 framework 里面包含了子 Pod 中的所有资源(如 .png, .bundle ),所以如果子 Pod 代码在获取自己的资源时,使用了 [NSBundle mainBundle],就会造成无法获取资源,发生错误。

例子

以我们自己的 NTFeedBack 库为例子,新建立一个工程,Podfile 如下:

source 'https://github.com/CocoaPods/Specs.git'
source 'https://*********/podspec.git'
platform :ios, '8.0'
use_frameworks!
target :Framework do
        pod 'NTFeedBack', '~> 3.2.3'
        link_with 'Framework'
end

运行完 pod install 以后,打开工程,在 AppDelegate.m 中添加头文件:

#import "NFBManager.h"

application:didFinishLaunchingWithOptions: 方法中添加下面代码:

[NFBManager configWithProduct:@"chexian_client" productId:@"10" version:@"1" channel:@"apple" deviceId:@"abcde"];
[NFBManager startMessagePolling];

然后运行应用,会崩溃,崩溃信息如下:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'

调试后会发现,问题出现在 NFBMessageDB.m 文件中 75 行的 managedObjectModel 方法返回了一个 nil 值,而这个 nil 值就是因为用 [NSBundle mainBundle] 获取资源而没有拿到产生的,代码如下:

-(NSManagedObjectModel *)managedObjectModel{
    static NSManagedObjectModel *managedObjectModel = nil;
    NSString *momPath ;
    momPath = [[NSBundle mainBundle] pathForResource:@"FBMessages" ofType:@"momd"];
    //NSLog(@"path %@",momPath);
    if (momPath){
        NSURL *momUrl = [NSURL fileURLWithPath:momPath];
        managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momUrl];
    }
    return managedObjectModel;
}

解决方法

网址 1、网址 2 很详细地说明了如何解决这个问题,简单总结一下:

  1. 先用下面的代码获取 framework 所在的 bundle

[NSBundle bundleForClass:<#ClassFromPodspec#>]

  1. 然后再用 URLForResource:withExtension: 方法来取到想要的其它资源

建议

  1. 建议通用库的作者都检查一下自己的库,看是否存在这样的情况;

  2. 使用 Swift 的项目也需要检查一下自己使用的库,看是否存在此问题。

你可能感兴趣的:(用 CocoaPods 集成 Swift 代码引入的 NSBundle 问题)