【问题标题】:IOS Static Framework with resources insideIOS静态框架,里面有资源
【发布时间】:2012-08-24 04:36:24
【问题描述】:

我正在尝试创建一个框架来保存我在项目中使用的一些通用代码。 我找到了在线教程并设法创建了一个框架,但我仍然有一个与资源(xib、图像等)相关的问题。

假设我有一个MainViewController.xib,它有一个使用test.pngUIImageView。所有这些都在我的框架包中。

当我在另一个项目中使用该框架时,我将它添加到“复制捆绑资源”构建阶段。问题是xib只能使用dummy.framework/Resources/MainViewController.xib之类的路径访问,而里面的UIImageView无法加载test.png

UIImageView 似乎会尝试从包的根目录加载 png,而不是从存储 xib 的相对文件夹中加载。

有没有人设法创建一个包含代码和资源的框架并在另一个项目中使用它?

【问题讨论】:

  • 嗨,andrei,你能告诉我你是如何将 .bundle 文件添加到框架目录中的吗...我无法做到这一点。我的 shell 脚本中可能有一些错误。

标签: ios frameworks uiimageview xib


【解决方案1】:

我知道这是一个旧线程,但为了防止新人犯同样的错误,这里是一个注释:

从 Xcode 6 和 iOS8 开始,Apple 内置了完全支持的第一方动态框架解决方案。有关更多信息,请查看此处:https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/WhatsNewXcode/Articles/xcode_6_0.html#//apple_ref/doc/uid/TP40014509-SW14

但最简单的方法是,创建一个新项目并选择 Cocoa Touch Framework 模板。

【讨论】:

  • 一切都很好,但是您是否真的设法在 Xcode 6 中创建的动态框架中包含图像资源。我自己尝试了所有方法,但无法正常工作!似乎很少有来自 Apple 的文档。
  • 是的。它相当简单,但可能并不明显。像平常一样简单地将您的图像包含在您的框架中,但是要加载它们,您需要引用框架的捆绑包。所以[NSBundle bundleWithIdentifier:@"com.<#company#>.<#framework#>"];
  • 是的,它与 imageNamed:inBundle:compatibleWithTraitCollection 一起工作。发送 inBundle:[NSBundle bundleWithClass[self class]] 或任何适合我使用图像的位置。
  • 是的,直到现在我们还没有真正尝试过提交。事实证明,您可以运行它,甚至可以使用新框架为 iOS7 分发企业版本。但是,当苹果检查您的构建以上传到商店时,它会拒绝它。几个工作人员在 WWDC 上说它可以在 iOS7 上运行,回头一看,他们从谈话中删除了 45 分钟的视频!
  • 嗨瑞恩。有什么建议如何在故事板或 xib 中使用框架中的图像?当我尝试时,我收到一个错误:无法加载从带有标识符“”的包中的笔尖引用的“”图像
【解决方案2】:

我创建了一个框架目标并访问其资产目录中的图像,我执行了以下操作:

UIImage *img = [UIImage imageNamed:@"IMAGE_NAME_HERE" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:[UITraitCollection traitCollectionWithDisplayScale:[UIScreen mainScreen].scale]];

【讨论】:

  • 非常感谢,我已经浪费了很多时间来寻找解决方案。这个工作:)
  • 这个适用于动态框架,而不是静态框架,因为对于静态框架 bundleForClass:self.class 返回主应用程序包。
【解决方案3】:

我不再手动管理框架,而是使用 and recommend CocoaPods


原答案:

  1. 使用提到的fake framework@wattson12。它也会编译和保存资源。
  2. this script 的启发,将其添加到您的目标以将资源复制到您的应用:

    SOURCE_PATH="${TARGET_BUILD_DIR}/MYFramework.framework/Resources/"
    TARGET_PATH="${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MYFrameworkResources.bundle"
    mkdir -p $TARGET_PATH
    cp -R $SOURCE_PATH $TARGET_PATH
    

您也可以只将框架拖到复制资源步骤,但随后您将添加不必要的标头和编译代码。

编辑

要使用 IB 中的这些资源,例如 png 文件,请替换:

MyImage

作者:

MYFrameworkResources.bundle/MyImage.png

它将预览损坏的图像图标,但在运行时会起作用。

从代码中加载一个 Nib:

[NSBundle loadNibNamed:@"MYFrameworkResources.bundle/MyNib" ...

最后,您可以将这些方法添加到 NSBundle 类别中,以方便访问我在您的主包或 MYFrameworkResources.bundle 中的 Nib 资源:

@implementation NSBundle (MyCategory)

+ (NSString *)pathForResource:(NSString *)name
                       ofType:(NSString *)extension
{
    // First try with the main bundle
    NSBundle * mainBundle = [NSBundle mainBundle];
    NSString * path = [mainBundle pathForResource:name
                                           ofType:extension];
    if (path)
    {
        return path;
    }

    // Otherwise try with other bundles
    NSBundle * bundle;
    for (NSString * bundlePath in [mainBundle pathsForResourcesOfType:@"bundle"
                                                          inDirectory:nil])
    {
        bundle = [NSBundle bundleWithPath:bundlePath];
        path = [bundle pathForResource:name
                                ofType:extension];
        if (path)
        {
            return path;
        }
    }

    NSLog(@"No path found for: %@ (.%@)", name, extension);
    return nil;
}

+ (NSArray *)loadNibNamed:(NSString *)name
                    owner:(id)owner
                  options:(NSDictionary *)options
{
    // First try with the main bundle
    NSBundle * mainBundle = [NSBundle mainBundle];
    if ([mainBundle pathForResource:name
                             ofType:@"nib"])
    {
        NSLog(@"Loaded Nib named: '%@' from mainBundle", name);
        return [mainBundle loadNibNamed:name
                                  owner:owner
                                options:options];
    }

    // Otherwise try with other bundles
    NSBundle * bundle;
    for (NSString * bundlePath in [mainBundle pathsForResourcesOfType:@"bundle"
                                                          inDirectory:nil])
    {
        bundle = [NSBundle bundleWithPath:bundlePath];
        if ([bundle pathForResource:name
                             ofType:@"nib"])
        {
            NSLog(@"Loaded Nib named: '%@' from bundle: '%@' ", name, bundle.bundleIdentifier);
            return [bundle loadNibNamed:name
                                  owner:owner
                                options:options];
        }
    }

    NSLog(@"Couldn't load Nib named: %@", name);
    return nil;
}

@end

它将首先查看您的应用程序包,然后查看 MYFrameworkResources.bundle 等。

【讨论】:

  • 谢谢,但是界面生成器仍然无法正确检测资源
  • 图片有问题吗? (预先设置路径就足够了)还是使用 Nibs?您还可以检查您的构建目录以查看资源在您的应用程序中的复制位置。
【解决方案4】:

为了在 Swift 3 中从动态框架加载图像:

UIImage(named: "name", in: Bundle(for: type(of: self)), compatibleWith: nil)

【讨论】:

  • 完美运行。我的场景是什么,我将自定义框架与资产一起使用,但无法使用资产图像。但这对我有用
  • 最初的问题是关于使用 static 框架中的资源
【解决方案5】:

基本框架不包含大部分资源,包含资源使用this "fake" framework library

您最终会得到一个 .embeddedframework 文件夹,其中包含实际框架,但还包含您添加到 Copy Bundle Resources 构建阶段的任何资源。我用它来包含 xib、核心数据模型、图像和 plist

【讨论】:

  • 是的,但是如果您(在框架中)有一个 xib,它使用也在框架中的资源(比方说图像)。你能在测试应用程序中加载 xib 吗?
  • 我面前没有那个项目,但我很确定没问题,试一试......
  • 我已经得出结论,我想要实现的目标实际上是不可能的。由于 Interface Builder 无法显示子文件夹中的图像(尽管它们在运行时工作),因此以捆绑形式提供任何资源确实不可行。最好的方法是简单地添加一个 zip 以及静态库,用户可以在其项目中使用该文件夹。
  • 您可以通过添加路径从 IB 引用嵌套在子文件夹中的资源:MyResources.bundle/image.png。它在 IB 中看起来不太好,但它会起作用
【解决方案6】:

简短的回答:你不能。

当您编译应用程序时,会使用“主”项目的资源生成捆绑包,忽略链接框架中的资源。这包括图像、xib、plist 等(任何非源文件)

您需要做的是将这些资源添加到您的主项目中,以便它们可以在您的应用程序中使用,这不是最快乐的方式,但它会起作用。

【讨论】:

  • 嗯,资源被复制了,但是在一个子文件夹中。
  • 这是最接近真实情况的答案。但是,您可以强制 xcode 从框架中复制资源,但它们将放置在主包的子文件夹中。这让加载它们很痛苦。
  • @doozMen 关心解释一下如何?
【解决方案7】:

从 Xcode 7 开始,我们现在可以使用资产目录。在我的实验中,我发现您可以在同一个工作空间中引用不同项目中的文件,从而无需在构建阶段对资产进行微观管理或担心目标。

【讨论】:

  • 这个答案与问题无关
猜你喜欢
  • 1970-01-01
  • 2015-02-09
  • 2015-06-06
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
相关资源
最近更新 更多