如何使用IBDesignable UIImageView在prepareForInterfaceBuilder中加载图像

我想在IBdevise的UIImageView加载一个示例图像,在界面生成器中显示,同时编辑界面。 以下代码不起作用,因为IB中的视图占位符保持为空(视图区域仅包含UIImageView文本):

 @IBDesignable class TestImageView : UIImageView { override func prepareForInterfaceBuilder() { //let bundle = NSBundle.mainBundle() let bundle = NSBundle(forClass: nil) let imagePath = bundle.pathForResource("Test", ofType: "jpg") self.image = UIImage(contentsOfFile: imagePath) } } 

注意:

  • 在IB中,视图的Custom Class类是正确的(TestImageView)
  • Test.jpg存在于项目中(如果我在IB中手动设置UIImageView的图像属性,图像显示出来)。
  • 我尝试了两种不同的方法来获取代码中的包

这是用Xcode 6 beta 3testing的。

更新 :在这两种情况下,我得到的包path是"/Applications/Temporary/Xcode6-Beta3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays" 。 在那条路上,图像显然不存在。

在Swift 3.0中,@ kasplat的代码已经改为:

 // DYNAMIC BUNDLE DEFINITION FOR DESIGNABLE CLASS let theBundle = Bundle(for: type(of: self)) // OR ALTERNATIVELY BY PROVDING THE CONCRETE NAME OF DESIGNABLE CLASS let theBundle = Bundle(for: RH_DesignableView.self) // AND THEN SUCCESSFULLY YOU CAN LOAD THE RESSOURCE let theImage = UIImage(named: "Logo", in: theBundle, compatibleWith: nil) 

尝试获得这样的class级包:

 let bundle = NSBundle(forClass: self.dynamicType) 

或者像这样指定类名

 let bundle = NSBundle(forClass: TestImageView.self) 

假设您的图像位于包中,例如Images.xcassets,则可以使用以下命令加载它:

 self.image = UIImage("Test", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection) 

请记住在尝试使用它之前检查您的图像是否为零。 我一直无法使用bundle.pathForResource正常的图像资产正常工作的图像path。 这里也没有出现UIImage的调用,你只需要指定名称和包,所以你必须使用特征集合。

这个问题涉及到:

xcode 6 IB_DESIGNABLE-不在接口构build器中从包加载资源

来自苹果的回应…

工程部门已经根据以下内容确定了此问题的行为:

我们不能真正做到这一点比指定包更容易。 你可能会说,“哦,让我们swizzle – [NSBundle mainBundle]”,但许多呼叫网站引用一个捆绑不通过那里(或通过CF API)。 有人可能会说,“好吧,那么我们至less该如何调整 – [UIImage imageNamed:]”。 这里的问题是主包没有单一的替代品。 您可能会同时加载多个实时视图包(框架或应用程序),因此我们不能只select一个作为主包。

开发人员需要了解捆绑以及如何从捆绑中获取图像。 开发人员应该使用UIImage(名为:inBundle:compatibleWithTraitCollection :)进行所有图像查找。

让我们快速的回答3

 let bundle = Bundle(for: self.classForCoder) ... UIImage(named: "AnImageInYourAssetsFolderPerhaps", in: bundle, compatibleWith: self.traitCollection)! 

我能够解决从当前的NSProcessInfo对象获取Interface Builder项目path的问题。 然后您可以从IB_PROJECT_SOURCE_DIRECTORIES键收集正确的path。

 override func prepareForInterfaceBuilder() { let processInfo = NSProcessInfo.processInfo() let environment = processInfo.environment let projectSourceDirectories : AnyObject = environment["IB_PROJECT_SOURCE_DIRECTORIES"]! let directories = projectSourceDirectories.componentsSeparatedByString(":") if directories.count != 0 { let firstPath = directories[0] as String let imagePath = firstPath.stringByAppendingPathComponent("PrepareForIBTest/Test.jpg") let image = UIImage(contentsOfFile: imagePath) self.image = image } } 

这个技巧在这个苹果开发者论坛post中的 bjhomerbuild议的WWDC 2014会议“Interface Builder的新function”中有介绍。

此外,我需要说, 它是需要切换到一个UIView子类 ,因为它似乎UIImageView的上下文不改变实时视图。

这将加载您的IB_Designable,或者如果您没有 – 默认图像。

 - (void)prepareForInterfaceBuilder { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; imagePic = imagePic ? [imagePic imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] : [UIImage imageNamed:@"goodIcon" inBundle:bundle compatibleWithTraitCollection:self.traitCollection]; } 

对于Swift 2和Xcode 7,界面已经改变。 应该使用

 let bundle = NSBundle(forClass: self.dynamicType) let image = UIImage(named: "imageName", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection) let imageView = UIImageView(image: image) 

我在我的项目中使用它,它对IB和设备都正常工作。

对于Swift 4(和3)使用这个:

 let image = UIImage(named: "foo", in: Bundle(for: type(of: self)), compatibleWith: traitCollection) 

这种方法普遍获得捆绑