这里有一个基本问题:我需要一个视图加载机制,它试图从Documents中下载的NIB创建视图,如果无法创建视图,则返回到主捆绑包。
在实现这一点之前,我已经进行了大量的研究和尝试,所以我想与其他人分享解决方案。
以下是步骤:
1) 以正常方式在主捆绑包中创建NIB。我建议使用一个指向文件夹的文件组,将所有将用于下载捆绑包的资产放在一起。让我们称之为NIB_Resources。
在项目导航器中的文件夹下创建NIB:
- 右键单击文件组
- 选择新文件
- 选择"用户界面",然后选择"视图">
2)为资产捆绑包添加目标。
- 单击目标面板中的+
- 在OS X下的Framework and Library类别中选择Bundle模板。它之所以属于该类别,是因为它是一种资产库类型
- 对于产品名称,请输入要调用资产库的名称。保持其他一切不变,然后选择要将产品添加到的项目
- 在新产品的构建设置中,将基本SDK从最新OS X更改为最新iOS
3)将资产添加到资产捆绑包中。
- 为新产品选择复制捆绑包资源构建阶段
- 拖放要包含在捆绑包中的资产。如果可以添加资源,光标将显示+图标
4)构建资产捆绑包。
- 为新创建的目标选择方案
- 选择iOS设备作为构建目标
- 构建
- 如果操作正确,新捆绑包的产品应该已从红色变为黑色,位于项目导航器的"产品"文件夹下
5)压缩资产包
- 右键单击Products文件夹中新建的产品,然后选择在Finder中显示
- 将捆绑包复制到某个位置,例如该项目专用目录中的某个文件夹
- 右键单击包含捆绑包以及可能的其他NIB文件、图像等的目录
- 选择压缩
6)将资产捆绑包上传到您可以下载访问的位置。
7) 下载压缩资产捆绑包:
下面的代码隐藏在便利函数中,在一个处理许多低级文件系统操作的便利文件中。FS前缀指的是文件系统。
在返回到主线程之前,可以从辅助线程调用FSDownloadTempFileWithURLString
。
我使用NSData
同步方法initWithContentsOfURL:
,因为调用可能是从辅助线程进行的。基本策略是在做任何必要的准备并将文件解压缩到Documents目录之前,将zip文件下载到一个临时位置(Caches目录通常是实现此目的的一个很好的候选目录)。苹果采用了在头文件中定义内联静态操作的方法。
//文档目录#define FSDocumentsDirectory[NSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)firstObject]//缓存目录#define FSCachesDirectory[NSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES)firstObject]/***获取缓存目录下文件的路径。给定的文件名可以有*多个文件分隔符。*/内联静态NSString*FSCachesPath(NSString*文件名){return[FSCachesDirectory字符串ByAppendingPathComponent:filename];}/***从指定的URL下载文件,并将其复制到缓存目录,文件名与URL的文件名相同。**返回结果。*/内联静态BOOL FSDownloadTempFileWithURLString(NSString*urlString){NSData*data=getDataFromURL(urlString);if(!data){//已记录错误返回FALSE;}NSString*path=FSCachesDirectory;NSString*filename=[urlString lastPathComponent];path=[path stringByAppendingPathComponent:filename];NSError*error=nil;if(![data writeToFile:path options:NSDataWritingAtomic error:&error]){NSLog(@"试图将文件写入%@@\n时出错",路径);NSLog(@"%@",错误);返回FALSE;}返回TRUE;}/***从指定的URL获取数据。*/内联静态NSData*getDataFromURL(NSString*urlString){NSString*escapedUrlString=[urlString字符串ByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];NSURL*url=[NSURL URLWithString:escapedUrlString];NSData*数据=[[NSData alloc]initWithContentsOfURL:url];if(!data){debugLog(@"无法下载文件:%@",escapedUrlString);返回零;}返回数据;}
8)使用SSZipArchive
或类似的东西将下载解压缩到Documents目录:
NSString*cachesPath=FSCachesPath(URL_RESOURCE_FILENAME);if(![SSSZipArchive unzip FileAtPath:cachesPath to Destination:FSDocumentsDirectory delegate:nil]){回来}
9)最后,尝试从Documents目录中捆绑包中的NIB文件加载视图,然后返回到主捆绑包。
下面的FSResourceNib
操作可以从试图从Nib加载视图的视图控制器调用,如下所示:
UIView*view=FSResourceNib(ResourcesBundle,nibName,self)
/***从documents目录中获取NIB,否则返回到bundle。**如果发生错误,则返回nil。*/内联静态UIView*FSResourceNib(NSString*bundleFilename,NSString*nibName,id所有者){UIView*resourceView=nil;//如果文档路径中不存在bundld,则使用主bundleNSString*resourcePath=FSDocumentsPath(bundleFilename);if([[NSFileManager defaultManager]fileExistsAtPath:resourcePath]){NSBundle*resourceBundle=[NSBundle bundleWithPath:resourcePath];@尝试{//尝试从给定的捆绑包加载NIBresourceView=[[resourceBundle loadNibNamed:nibName所有者:所有者选项:nil]lastObject];}@catch(NSException*异常){//什么都不做-将尝试主捆绑包}}//如果从给定捆绑包加载失败,请尝试从主捆绑包加载if(!resourceView){NSBundle*resourceBundle=[NSBundle mainBundle];@尝试{resourceView=[[resourceBundle loadNibNamed:nibName所有者:所有者选项:nil]lastObject];}@catch(NSException*异常){//不执行任何操作-将返回nil,表示发生错误}}return resourceView;}