适用情况
iOS 8.0 以上支持
通过 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 很详细地说明了如何解决这个问题,简单总结一下:
- 先用下面的代码获取 framework 所在的 bundle
[NSBundle bundleForClass:<#ClassFromPodspec#>]
- 然后再用
URLForResource:withExtension:
方法来取到想要的其它资源
建议
建议通用库的作者都检查一下自己的库,看是否存在这样的情况;
使用 Swift 的项目也需要检查一下自己使用的库,看是否存在此问题。