我有一个iPhone应用程序,有不同的皮肤风格,不同的艺术资产和声音,但所有相同的代码.
我已经设置了多个目标,但我遇到的问题是我必须有一组不同的UIBuilder nib文件,每个目标每个视图一个,设置为指向该目标的正确艺术.
这有点令人沮丧,因为如果我对一个nib文件进行更改,我必须在所有其他nib文件中手动进行相同的更改,相同的连接等.我还为不同的皮肤添加了不同名称的所有资源,因此它们不会在项目中发生冲突.所以,如果我有目标,A和B,我有a_main_menu.png
,b_main_menu.png
... a_FooViewController.xib
,b_FooViewController.xib
...等等.
有没有办法制作一个nib文件,指向具有相同名称的资产,但是在......嗯,不同的捆绑包?捆绑是什么?我可以想象在我的代码中修复这样的东西(可能在加载它之前搜索和替换N中的B,甚至可能足够好),虽然我没有尝试过,但这很难看.
对于我的第一组应用程序来说,这是一个可管理的策略(尽管远非最佳),但随着我的东西变得越来越复杂,我的构建器文件保持同步变得非常困难,而且这种工作方式并不是很干净.除了放弃uibuilder并在代码中创建我的观点之外,还有更好的方法吗?
如果这在xcode/builder级别工作会很好,所以构建器会尊重我当前的目标,并在我工作的时候展示该目标的艺术......但我可以没有那样生活,就像我可以选择在运行时的当前艺术集,我只能在构建器中使用一组.我也可以通过一个目标并在构建之前手动替换所有艺术品来完成一组笔尖,但这也不是很好.
最重要的是,如果我可以混合使用这两种策略 - 比如我有一个目标,其中有一个具有一个视图,而不是以不同的方式布局......但这是可选的.
我问的是正确的问题吗?
谢谢!
一种方法是将所有图稿移动到一个单独的包中,并在运行时动态加载它(有点像"媒体插件").
创建一个单独的项目,然后选择"Mac OS X/Framework&Library/Bundle".比如说,叫它media.bundle
.
将所有作品移动到此项目中.
为了简化操作,请向目标添加一个额外的"运行脚本"步骤,将构建目录中的构建输出复制到主项目下的子文件夹中.为了使其更加简单,请将媒体包添加为主项目中的依赖项目,以便自动重建.
在您的主项目中,您将需要这两种方法.你可以在BundleUtils
类下面创建静态方法:
+ (NSString *) bundleDirectoryFor:(NSString *) bundleName { NSString* basePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.bundle", bundleName]]; return [[NSBundle bundleWithPath:basePath] resourcePath]; } + (NSString *) resourceInBundle:(NSString *)bundleName fileName:(NSString *)fileName { NSString *bundlePath = [BundleUtils bundleDirectoryFor:bundleName]; return [bundlePath stringByAppendingPathComponent:fileName]; }
现在,每当您想要访问捆绑包中的图稿时,您都可以通过以下方式获取正确文件的路径:
NSString* imageFile = [BundleUtils resourceInBundle:@"media.bundle" fileName:@"image.jpg"]; UIImage* image = [UIImage imageNamed:imageFile];
显然,名称"media.bundle"可以在运行时替换为另一个名称,因此您可以根据应用程序的需要切换到其他捆绑包.这也是支持可下载内容的便捷方式(例如,作为付费附加组件).
需要注意的是:这假设您需要在运行时通过代码动态加载图像.但是,您还有静态NIB文件,其中嵌入了媒体.您必须找到一种方法来使静态NIB文件使用动态方法来解析媒体文件名.一种方法是使用MethodSwizzling并监视具有类型前缀的文件路径,例如"media:image.png"并重定向它们以使用BundleUtil方法.
另一种方法是使用IB进行布局,然后使用nib2objc将其转换为Obj-C代码,然后替换插件包机制.
希望这可以帮助.