xcode 6 IB_DESIGNABLE-不在“接口”构建器中从bundle加载资源 [英] xcode 6 IB_DESIGNABLE- not loading resources from bundle in Interface builder

查看:54
本文介绍了xcode 6 IB_DESIGNABLE-不在“接口”构建器中从bundle加载资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用描述的新IB_DESIGNABLE选项创建一个在Interface Builder中实时更新的自定义控件这里

I am trying to make a custom control that updates live in Interface Builder using the new IB_DESIGNABLE option described here.

- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();

CGRect myFrame = self.bounds;
CGContextSetLineWidth(context, 10);
CGRectInset(myFrame, 5,5);
[[UIColor redColor] set];
UIRectFrame(myFrame);

NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath;

plistPath = [bundle pathForResource:@"fileExample" ofType:@"plist"];
UIImage *tsliderOff = [UIImage imageNamed:@"btn_slider_off.png"];

[tsliderOff drawInRect:self.bounds];
}

当我在模拟器中运行时,我得到一个带有我的图像的红色框中心(如预期):

When I run in the simulator, I get a red box with my image in the center (as expected):

但是当我尝试使用Interface Builder时,它只显示为一个红色框(中间没有图像):

But when I try use the Interface Builder, it only shows up as a red box (no image in the middle):

当我调试它时:编辑器 - >调试所选视图,它显示从包中加载的任何内容没有。 plistPath和tsliderOff都显示为nil。

When I debug it: Editor->Debug Selected Views, it reveals that anything loaded from the bundle is nil. The plistPath and tsliderOff both appear as nil.

我确保btn_slider_off.png包含在Targets-> myFrameWork-> Build Phases-> Copy Bundle Resources中。

I made sure that btn_slider_off.png was included in the Targets->myFrameWork->Build Phases->Copy Bundle Resources.

任何想法为什么Interface Builder在编辑期间没有看到png文件,但在运行时显示正常?如果我无法加载任何图像来渲染,创建在Interface Builder中渲染的自定义视图有点受限...

Any idea why Interface Builder doesn't see the png file during editing, but shows ok when running? "Creating a Custom View that Renders in Interface Builder" is a little limited if I can't load any images to render...

根据rickster的解决方案进行编辑

edit based on solution by rickster

rickster向我指出解决方案 - 问题是文件不在mainBundle中,它们存在于[NSBundle] bundleForClass:[self class]];看来[UIImage imageNamed:@btn_slider_off.png]自动使用mainBundle。

rickster pointed me to the solution - the problem is that the files don't live in mainBundle, they live in [NSBundle bundleForClass:[self class]]; And it appears that [UIImage imageNamed:@"btn_slider_off.png"] automatically uses mainBundle.

以下代码有效!

#if !TARGET_INTERFACE_BUILDER
NSBundle *bundle = [NSBundle mainBundle];
#else
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
#endif
NSString *fileName = [bundle pathForResource:@"btn_slider_off" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:fileName];
[image drawInRect:self.bounds];


推荐答案

截至首次询问此问题时,创建一个IB可设计的控制需要将其打包在框架目标中。您不必再这样做了 - 运送Xcode 6.0(及更高版本)也将从您的应用目标预览IB可设计的控件。但问题和解决方案是一样的。

As of when this question was first asked, creating an IB-designable control required packaging it in a framework target. You don't have to do that anymore — the shipping Xcode 6.0 (and later) will preview IB-designable controls from your app target, too. However, the problem and the solution are the same.

为什么? [NSBundle mainBundle] 返回当前正在运行的应用程序的主要包。
当您从框架中调用它时,您将根据加载框架的应用程序返回另一个包。当您运行应用程序时,您的应用程序会加载框架。当您在IB中使用该控件时,一个特殊的Xcode助手应用程序会加载该框架。即使您的IB可设计控件在您的应用目标中,Xcode也会创建一个特殊的帮助应用程序来运行IB内部的控件。

Why? [NSBundle mainBundle] returns the primary bundle of the currently running app. When you call that from a framework, you're getting a different bundle returned based on which app is loading your framework. When you run your app, your app loads the framework. When you use the control in IB, a special Xcode helper app loads the framework. Even if your IB-designable control is in your app target, Xcode is creating a special helper app to run the control inside of IB.

解决方案?在Swift中调用 + [NSBundle bundleForClass:] (或 NSBundle(forClass :))/ / code>。这将为您提供包含您指定的任何类的可执行代码的包。 (您可以在那里使用 [self class] / self.dynamicType ,但要注意结果将针对在不同的捆绑包。)

The solution? Call +[NSBundle bundleForClass:] instead (or NSBundle(forClass:) in Swift). This gets you the bundle containing the executable code for whichever class you specify. (You can use [self class]/self.dynamicType there, but beware the result will change for subclasses defined in different bundles.)

如果您正在使用框架方法 - 这对某些应用程序很有用,即使IB设计控件不再需要它 - 最好是将图像资源与使用它们的代码放在同一框架中。如果您的框架代码期望使用运行时通过任何应用程序加载框架提供的资源,那么使其成为IB可设计的最好方法就是伪造它。在控件中实现 prepareForInterfaceBuilder 方法,让它从已知位置加载资源(如框架包或Xcode工作区中的静态路径)。

If you're using the framework approach — which can be useful for some apps even though it's no longer required for IB-designable controls — it's best to put image resources in the same framework with the code that uses them. If your framework code expects to use resources provided at run time by whatever app loads the framework, the best thing to do for making it IB-designable is to fake it. Implement the prepareForInterfaceBuilder method in your control and have it load resources from a known place (like the framework bundle or a static path in your Xcode workspace).

这篇关于xcode 6 IB_DESIGNABLE-不在“接口”构建器中从bundle加载资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆