这是基本问题:我需要一个视图加载机制,尝试从 Documents 中下载的 NIB 创建一个视图,如果无法创建视图,则返回到主包。
在让它发挥作用之前,我经历了很多研究和反复试验,所以我想与其他人分享解决方案。
这是基本问题:我需要一个视图加载机制,尝试从 Documents 中下载的 NIB 创建一个视图,如果无法创建视图,则返回到主包。
在让它发挥作用之前,我经历了很多研究和反复试验,所以我想与其他人分享解决方案。
以下是步骤:
1) 以正常方式在主包中创建 NIB。我建议使用指向文件夹的文件组,以将所有资源放在一起,以用于下载的捆绑包。我们称之为NIB_Resources。
在 Project Navigator 中的文件夹下创建 NIB:
2) 为资产包添加一个目标。
3) 将资产添加到资产包。
4) 构建资产包。
5) 压缩资产包
6) 将资产包上传到您有权下载的位置。
7) 下载压缩包:
下面的代码隐藏在便利函数中,在一个处理许多低级文件系统操作的便利文件中。FS 前缀是指文件系统。
FSDownloadTempFileWithURLString
在返回主线程之前,可以从辅助线程调用。
我使用NSData
同步方法,initWithContentsOfURL:
因为调用很可能是从辅助线程进行的。基本策略是将 zip 文件下载到一个临时位置(Caches 目录通常是一个很好的选择),然后再进行任何必要的准备并将文件解压缩到 Documents 目录。Apple 采用了在头文件中定义内联静态操作的方法。
//文档目录 #define FSDocumentsDirectory [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] //缓存目录 #define FSCachesDirectory [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] /** * 获取缓存目录下文件的路径。给定的文件名可以有 * 多个文件分隔符。 */ 内联静态 NSString* FSCachesPath(NSString *filename) { return [FSCachesDirectory stringByAppendingPathComponent:filename]; } /** * 从指定的 URL 下载文件,并复制到缓存目录,与 URL 的文件名相同的文件名。 * * 返回结果。 */ 内联静态 BOOL FSDownloadTempFileWithURLString(NSString *urlString) { NSData *data = getDataFromURL(urlString); 如果(!数据){ //错误已经记录 返回错误; } NSString *path = FSCachesDirectory; NSString *filename = [urlString lastPathComponent]; path = [path stringByAppendingPathComponent:filename]; NSError *error = nil; if (![data writeToFile:path options:NSDataWritingAtomic error:&error]) { NSLog(@"尝试将文件写入时发生错误:%@\n", path); NSLog(@"%@", 错误); 返回错误; } 返回真; } /** * 从指定的 URL 获取数据。 */ 内联静态 NSData* getDataFromURL(NSString *urlString) { NSString *escapedUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:escapedUrlString]; NSData *data = [[NSData alloc] initWithContentsOfURL:url]; 如果(!数据){ debugLog(@"无法下载文件:%@", escapedUrlString); 返回零; } 返回数据; }
8) 使用SSZipArchive
或类似的方法将下载文件解压缩到 Documents 目录:
NSString *cachesPath = FSCachesPath(URL_RESOURCE_FILENAME); if (![SSZipArchive unzipFileAtPath:cachesPath toDestination:FSDocumentsDirectory delegate:nil]) { 返回; }
9) 最后,尝试从 Documents 目录中包中的 NIB 文件加载视图,然后返回到主包。
下面的FSResourceNib
操作可以从试图从 Nib 加载视图的视图控制器中调用,如下所示:
UIView *view = FSResourceNib(ResourcesBundle, nibName, self);
/** * 从文档目录中获取 NIB,否则回退到捆绑包。 * * 如果发生错误,则返回 nil。 */ 内联静态 UIView* FSResourceNib(NSString *bundleFilename, NSString *nibName, id owner) { UIView *resourceView = nil; //如果文档路径中不存在bundld,则使用主包 NSString *resourcePath = FSDocumentsPath(bundleFilename); if ([[NSFileManager defaultManager] fileExistsAtPath:resourcePath]) { NSBundle *resourceBundle = [NSBundle bundleWithPath:resourcePath]; @尝试 { //尝试从给定的包中加载NIB resourceView = [[resourceBundle loadNibNamed:nibName owner:owner options:nil] lastObject]; } @catch (NSException *异常) { //什么都不做 - 将尝试主包 } } //如果从给定包加载失败,尝试从主包加载 如果(!resourceView){ NSBundle *resourceBundle = [NSBundle mainBundle]; @尝试 { resourceView = [[resourceBundle loadNibNamed:nibName owner:owner options:nil] lastObject]; } @catch (NSException *异常) { // 什么都不做 - 将返回 nil,表示发生了错误 } } 返回资源视图; }