是否有可能通过NSBundles共享图像?
道歉的含糊不清的问题标题...是否有可能通过NSBundles共享图像?
这里是我的方案:
我动态地从笔尖存储在NSBundles文件
BOOL bundlePathExists = [fm fileExistsAtPath:bundlePath];
if (bundlePathExists) {
NSBundle *tempBundle = [NSBundle bundleWithPath:bundlePath];
UIViewController *vc = [[UIViewController alloc] initWithNibName:nibName bundle:tempBundle];
[self.view addSubview:vc.view];
}
(注加载UIView的内容:上面是一个简化了实际代码的摘录,因为不会混淆问题的性质 - 做这件事的机制相对有据可查here)
这些nib文件包含一个数字的图像,其中一些对于该包是独一无二的,还有一些是在多个包之间共享的。
我希望能够存储主包中常见的图像,因此它们不会占用其他包中的空间,并最大限度地减少整个项目的维护 - 例如,如果我改变了那些常见的图像之一,我宁愿不必重建它引用的每一个束。
我知道我可以编程方式做到这一点通过使用
[commonImageViewIvar setImage:[UIImage imageWithName:commonImageName]];
但是我更愿意实现这一目标而无需编写自定义代码为每个视图(即实例化的视图控制器不是按笔尖定制的,因此所有的信息需求存储在笔尖)
如这里承诺是我想出了一个解决方案:
束文件本身所描述的here下载。要添加这里列出的信息,我发现如果您先在iPhone应用程序中创建视图,则可以在模拟器中预览它们。然后,可以创建一个新项目作为捆绑包,然后将所有图像文件& xib & .h文件拖放到新项目中。不要拖动.m文件,因为这会造成构建问题。那么请确保项目设置将BASE SDK定义为“最新的IOS”,而不是将要选择的默认Mac OS X设置。然后你可以通过双击来编辑xib。通过取消选择该文件的“目标”列,可以从构建中取消选择任何公用文件。请参阅本答复文章后面的“其他信息”。
有一次我在从服务器zip文件下载的每捆,我使用下面的方法我编写用于此目的:
-(NSArray *) imageFileExtensions {
return [NSArray arrayWithObjects:@".png",@".gif",@".jpg",@".jpeg",@".bmp", nil];
}
和
-(void) cloneImageFilesInPath:(NSString *)path toPath:(NSString*)clonePath {
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *extensions = [self imageFileExtensions];
if ([fm fileExistsAtPath:path]) {
NSArray *files = [fm contentsOfDirectoryAtPath:path error:nil];
for (NSString *file in files){
for (NSString *ext in extensions) {
if ([file hasSuffix:ext]) {
NSString *targetFile = [clonePath stringByAppendingPathComponent:file];
if (![fm fileExistsAtPath:targetFile]) {
[fm createSymbolicLinkAtPath:targetFile withDestinationPath:[path stringByAppendingPathComponent:file] error:nil];
}
break;
}
}
}
}
}
这些方法创建扫描主应用程序包目录中,并且对于不在定制包目录中的每个图像文件,将在定制包目录内创建一个符号链接以指向主应用程序包目录。
他们在我的应用程序委托调用如下:
...(insert code to unzip the file to bundlePath here)...
[self cloneImageFilesInPath:[[NSBundle mainBundle] bundlePath] toPath:bundlePath];
信息
创建实际的包,我犯了一个单独的应用程序,从自定义包目录中删除所有图像文件,如果这些文件名存在于包含部署在主应用程序包中的公用图像文件的目录中。我后来发现,您可以通过取消选择该文件的目标列复选框来阻止xcode从构建中包含某些文件,因此不一定需要执行此步骤 - 但如果您有大量的创建视图,则可能更容易离开他们在捆绑中,并使用这种方法去除它们。
-(void) removeDuplicatedImageFilesInPath:(NSString *)sourcePath fromTargetPath:(NSString*)path {
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *extensions = [self imageFileExtensions];
if ([fm fileExistsAtPath:path]) {
NSArray *files = [fm contentsOfDirectoryAtPath:sourcePath error:nil];
for (NSString *file in files){
for (NSString *ext in extensions) {
if ([file hasSuffix:ext]) {
NSString *targetPath = [path stringByAppendingPathComponent:file];
if ([fm fileExistsAtPath:targetPath]) {
[fm removeItemAtPath:targetPath error:nil];
}
break;
}
}
}
}
}
用于处理压缩文件
更多信息,我选择使用ObjectiveZip(以下通过海报here的建议。为了简化任务,我裹着这在以下2个应用程序的委托方法(一个是在实际应用中使用,另一个在脱机包创建应用程序)
在主应用
-(void) unzipArchive:(NSString *)zipFileName toPath:(NSString *)path {
NSFileManager *fm = [NSFileManager defaultManager];
ZipFile *unzipFile = [[ZipFile alloc] initWithFileName:zipFileName mode:ZipFileModeUnzip];
NSArray *infos= [unzipFile listFileInZipInfos];
[unzipFile goToFirstFileInZip];
for (FileInZipInfo *info in infos) {
ZipReadStream *read1= [unzipFile readCurrentFileInZip];
NSMutableData *fileData = [[[NSMutableData alloc] initWithLength:info.length] autorelease];
int bytesRead1 = [read1 readDataWithBuffer:fileData];
if (bytesRead1 == info.length) {
NSString *fileName = [path stringByAppendingPathComponent:info.name ];
NSString *filePath = [fileName stringByDeletingLastPathComponent];
[fm createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
[fileData writeToFile:fileName atomically:YES];
}
[read1 finishedReading];
[unzipFile goToNextFileInZip];
}
[unzipFile close];
[unzipFile release];
}
和自定义捆绑包创建离线应用程序。
-(void) createArchive:(NSString *) zipFileName usingPath:(NSString *)path {
NSArray *files = [self filesInDirectory:path];
ZipFile *zipFile= [[ZipFile alloc] initWithFileName:zipFileName mode:ZipFileModeCreate];
for (NSString *file in files) {
NSString *fileNameForZip = [file substringFromIndex:path.length];
ZipWriteStream *stream= [zipFile writeFileInZipWithName:fileNameForZip fileDate:[NSDate dateWithTimeIntervalSinceNow:-86400.0] compressionLevel:ZipCompressionLevelBest];
[stream writeData:[NSData dataWithContentsOfFile:file]];
[stream finishedWriting];
}
[zipFile close];
[zipFile release];
}
注:先前的方法依赖于以下2种方法,其创建一个包含在给定路径中的所有文件的完全合格的路径一个NSArray(递归到子目录)
-(void)loadFilesInDirectory:(NSString *)path intoArray:(NSMutableArray *)files {
NSFileManager *fm = [NSFileManager defaultManager];
NSMutableArray *fileList = [NSMutableArray arrayWithArray:[fm contentsOfDirectoryAtPath:path error:nil]];
for (NSString *file in fileList) {
BOOL isDirectory = NO;
NSString *filePath = [path stringByAppendingPathComponent:file];
if ([fm fileExistsAtPath:filePath isDirectory:&isDirectory]) {
if (isDirectory) {
[self loadFilesInDirectory:filePath intoArray:files];
} else {
[files addObject:filePath];
};
};
}
}
-(NSArray *)filesInDirectory:(NSString *)path {
NSMutableArray *files = [NSMutableArray array];
[self loadFilesInDirectory:path intoArray:files];
return files;
}
它出现我可以使用设备上的文件夹文件夹中的符号链接(例如,通过链接myApp.app/Documents/instance.bundle/commonImage.png - > myApp.app/commonImage.png)来完成我所需要的操作。我将很快发布我的通用解决方案。 – unsynchronized
编辑原始问题以正确链接(请参阅上面相对良好的“此处”) - 对试图遵循该链接的任何人致歉。 – unsynchronized