【问题标题】:One nib, different assets. Bundles?一个笔尖,不同的资产。捆绑?
【发布时间】:2010-10-07 00:49:49
【问题描述】:

我有一个 iPhone 应用程序,它具有不同的外观风格,具有不同的艺术资产和声音,但代码都是相同的。

我已经设置了多个目标,但我遇到的问题是我必须有一组不同的 UIBuilder nib 文件,每个目标每个视图一个,设置为指向正确的艺术目标。

这有点令人沮丧,因为如果我对一个 nib 文件进行更改,我必须在所有其他 nib 文件中手动进行相同的更改、相同的连接等。我还为不同的皮肤添加了不同名称的所有资产,这样它们就不会在项目中发生冲突。所以,如果我有目标 A 和 B,我有 a_main_menu.pngb_main_menu.png...a_FooViewController.xibb_FooViewController.xib...等。

有没有办法制作一个指向同名资产的 nib 文件,但它们位于...嗯,不同的捆绑包中?这就是捆绑包的用途吗?我可以想象在我的代码中修复这样的事情(可能在加载之前在笔尖中搜索并替换 A 为 B 甚至可能已经足够好了),虽然我还没有尝试过,这很丑陋。

对于我的第一组应用程序来说,这是一个易于管理的策略(尽管远非最佳),但随着我的东西变得越来越复杂,让我的构建器文件保持同步变得非常困难,而且这不是一个非常干燥的方法工作。除了放弃 uibuilder 并在代码中创建我的视图之外,还有更好的方法吗?

如果这在 xcode/builder 级别上工作会很好,所以 builder 会尊重我当前的目标并在我工作时展示该目标的艺术......但我也许可以没有它,就像如果我可以在运行时选择当前的一组艺术作品,而我只能使用 builder 中的一组作品。我也可以使用一组笔尖,通过一个目标并在构建之前手动替换所有艺术作品,但这也不是很好。

如果我可以混合使用这两种策略,最好的办法就是——例如,如果我有一个目标具有多个视图中的一个视图,但必须以不同的方式布局...但这是可选的。

我问的问题对吗?

谢谢!

【问题讨论】:

    标签: iphone cocoa-touch xcode interface-builder target


    【解决方案1】:

    这样做的一种方法是将所有艺术品移动到一个单独的包中,并在运行时动态加载它(有点像“媒体插件”)。

    • 创建一个单独的项目并选择“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 代码,然后替换插件捆绑机制。

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      假设每个应用一次只需要一个皮肤,并且您要创建多个具有不同主题的应用,我将在我的源代码管理中创建一个分支,然后替换必要的资产。您保留一个包含所有默认资产的主分支,然后将主分支中的代码更改合并到您的皮肤分支中,以保持一切同步。

      Git 让这变得超级简单。

      【讨论】:

        【解决方案3】:

        我认为最好的选择是使用 git 之类的东西。

        如果您使用 git,您可以拥有一个包含主源代码和逻辑的主分支,并拥有针对您的应用程序的每种特定风格具有不同数据/图像集的子分支。在这个解决方案中,XCode 甚至都不知道发生了什么。

        【讨论】:

          【解决方案4】:

          我认为这就是 viewDidLoad 的用途,要自定义更多,在这里您可以更改图像路径。

          【讨论】:

            【解决方案5】:

            这对我有用:

            1 个项目。 2个目标a,b。 a、b 的 2 个图像文件夹。

            controller.m 及其 nib 文件适用于两个目标。

            为目标 a 和 b 的图像创建单独的文件系统文件夹。

            导入一个图像文件夹到目标a(“将文件添加到xy”->“添加到目标a/b”),另一个到目标b。确保使用“为添加的文件夹创建组”选项。不要选择“文件夹引用”选项。

            当我构建目标 a 时,我从文件夹 a 中获取了一个包含图像的应用程序;当我为 b 构建时,它使用文件夹 b 来保存图片。

            【讨论】:

              猜你喜欢
              • 2020-11-29
              • 2013-03-11
              • 2011-05-08
              • 1970-01-01
              • 1970-01-01
              • 2013-08-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多