内部有资源的 IOS 静态框架
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12180113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
IOS Static Framework with resources inside
提问by Andrei Stanescu
I'm trying to create a framework that keeps some common code I use around in my projects. I found online tutorials and managed to create a framework but I still have one problem related to resources (xibs, images, etc).
我正在尝试创建一个框架,以保留我在项目中使用的一些通用代码。我找到了在线教程并设法创建了一个框架,但我仍然有一个与资源(xib、图像等)相关的问题。
Let's say I have a MainViewController.xib
which has a UIImageView
using a test.png
. All these are in my framework package.
假设我有MainViewController.xib
一个UIImageView
using a test.png
。所有这些都在我的框架包中。
When I use the framework in another project, I add it to the "Copy Bundle Resources" build phase. The problem is that the xib is only accessible using a path like dummy.framework/Resources/MainViewController.xib
and the UIImageView
inside can't load test.png
.
当我在另一个项目中使用该框架时,我将其添加到“复制捆绑资源”构建阶段。问题是只能使用类似路径访问 xibdummy.framework/Resources/MainViewController.xib
并且UIImageView
内部无法加载test.png
.
It seems that the UIImageView will try to load the png from the root of the bundle, and not from the relative folder where the xib is also stored.
似乎 UIImageView 将尝试从包的根目录加载 png,而不是从也存储 xib 的相对文件夹中加载 png。
Has anybody managed to create a framework with code and resources and use it in another project?
有没有人设法用代码和资源创建一个框架并在另一个项目中使用它?
采纳答案by Ismael
Short answer: you can't.
简短的回答:你不能。
When you compile the app, the bundle is generated with the resources of the "main" project, ignoring the resources in linked frameworks. This includes images, xib's, plist's, etc. (anything that isn't a source file)
编译应用程序时,会使用“主”项目的资源生成包,忽略链接框架中的资源。这包括图像、xib、plist 等(任何不是源文件的内容)
What you need to do is add those resources to your main project so that they are available for use inside your application, not the happiest way around it but it'll work.
您需要做的是将这些资源添加到您的主项目中,以便它们可以在您的应用程序中使用,这不是最愉快的方式,但它会起作用。
回答by Ryan Poolos
I know this is an old thread, but to keep new people from making the same mistakes here is a note:
我知道这是一个旧线程,但为了防止新人犯同样的错误,这里有一个注释:
As of Xcode 6 and iOS8, Apple has a fully supported first party Dynamic Framework solution built in. For more information look here: https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/WhatsNewXcode/Articles/xcode_6_0.html#//apple_ref/doc/uid/TP40014509-SW14
从 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
But the short of it is, create a new project and choose the Cocoa Touch Framework template.
但简而言之,创建一个新项目并选择 Cocoa Touch Framework 模板。
回答by devinross
I created a framework target and to access images inside its asset catalog I did the following:
我创建了一个框架目标并访问其资产目录中的图像,我执行了以下操作:
UIImage *img = [UIImage imageNamed:@"IMAGE_NAME_HERE" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:[UITraitCollection traitCollectionWithDisplayScale:[UIScreen mainScreen].scale]];
回答by Rivera
I don't manually manage frameworks anymore but use and recommendCocoaPodsinstead.
Original answer:
原答案:
- Use the fake framework@wattson12 mentioned. It will compile and save the resources as well.
Inspired by this script, add this to your target to copy the resources to your app:
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
- 使用提到的假框架@wattson12。它也会编译和保存资源。
灵感来自这个脚本,将它添加到你的目标的资源复制到你的应用程序:
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
You could also just drag the framework to your Copy Resources step, but then you'll be adding unnecessary headers and compiled code as well.
您也可以将框架拖到 Copy Resources 步骤,但随后您还将添加不必要的头文件和编译代码。
Edit
编辑
To use these resources from IB, for instance a png file, replace:
要使用来自 IB 的这些资源,例如 png 文件,请替换:
MyImage
by:
经过:
MYFrameworkResources.bundle/MyImage.png
It will preview a broken image icon but will work when running.
它将预览损坏的图像图标,但在运行时会起作用。
Load a Nib from code:
从代码加载 Nib:
[NSBundle loadNibNamed:@"MYFrameworkResources.bundle/MyNib" ...
Finally you can add these methods in a NSBundle category to ease access to Nib resources that my be in your main bundle or in MYFrameworkResources.bundle:
最后,您可以将这些方法添加到 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
It will first look into your application bundle and then in MYFrameworkResources.bundle, etc.
它将首先查看您的应用程序包,然后查看 MYFrameworkResources.bundle 等。
回答by Luca Torella
In order to load an image from a dynamic framework in Swift 3:
为了从Swift 3 中的动态框架加载图像:
UIImage(named: "name", in: Bundle(for: type(of: self)), compatibleWith: nil)
UIImage(named: "name", in: Bundle(for: type(of: self)), compatibleWith: nil)
回答by wattson12
Basic frameworks do not include most kinds of resources, to include resources use this "fake" framework library
基本框架不包括大多数类型的资源,要包括资源使用这个“假”框架库
You end up with a .embeddedframework folder which contains the actual framework, but also includes any resources which you add to the Copy Bundle Resources build phase. Ive used it to include xibs, core data models, images, and plists
您最终会得到一个包含实际框架的 .embeddedframework 文件夹,但也包含您添加到复制捆绑资源构建阶段的任何资源。我用它来包含 xibs、核心数据模型、图像和 plists
回答by leerie simpson
As of Xcode 7 we can now use Asset Catalogs. In my experiments I've found that u can reference files in the same workspace bit different projects removing the need to micro manage assets in build phases or worrying about targets.
从 Xcode 7 开始,我们现在可以使用资产目录。在我的实验中,我发现您可以在同一个工作区中引用不同项目中的文件,从而无需在构建阶段微管理资产或担心目标。