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

时间:2014-07-10 08:29:53

标签: ios uiimageview swift

我想在IB可设计的UIImageView中加载示例图像,以便在编辑界面时在Interface Builder中显示。以下代码不起作用,因为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 3测试。

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

7 个答案:

答案 0 :(得分:53)

尝试像这样获取类的包:

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获取图像路径以正常使用普通图像资源。也没有看起来像UIImage调用,你只指定名称和包,所以你必须使用特征集。

这个问题与:

有关

xcode 6 IB_DESIGNABLE- not loading resources from bundle in Interface builder

Apple的回应......

  

Engineering已确定此问题的行为符合预期   以下内容:

     

我们无法比指定捆绑包更容易。您   可能会说,"哦,让我们调侃 - [NSBundle mainBundle]",但很多   引用捆绑的呼叫网站不会通过那里(或去   通过CF API)。有人可能会说"好吧,那我们怎么样   最少调的 - [UIImage imageNamed:]"。这里的问题是那里   不是主要捆绑的唯一替代品。你可能有多个   实时视图包(框架或应用程序)一次加载,所以我们   不能选择一个作为主要的捆绑。

     

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

答案 1 :(得分:17)

更新了Swift 4.2

当您实例化UIImage(使用UIImage(名称:" SomeName")时,应用程序将在您的主程序包中查找资产,这通常可以正常工作。但是当您在设计时,InterfaceBuilder在一个单独的包中保存可设计视图的代码(编译设计)。

所以解决方案是:动态定义捆绑包,因此可以在设计,编译和运行时找到您的文件:

    // DYNAMIC BUNDLE DEFINITION FOR DESIGNABLE CLASS
    let dynamicBundle = Bundle(for: type(of: self))

    // OR ALTERNATIVELY BY PROVDING THE CONCRETE NAME OF YOUR DESIGNABLE VIEW CLASS
    let dynamicBundle = Bundle(for: YourDesignableView.self)

    // AND THEN SUCCESSFULLY YOU CAN LOAD THE RESSOURCE
    let image = UIImage(named: "Logo", in: dynamicBundle, compatibleWith: nil)

答案 2 :(得分:7)

让我们快速回答一下

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

答案 3 :(得分:5)

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

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
    }
}

WWDC 2014 411会议" Interface Builder"中的新功能描述了这种技术。正如bjhomer在Apple Developer Forums post中所建议的那样。

此外,我需要说需要切换到UIView子类,因为UIImageView的外观似乎在实时视图中没有变化

答案 4 :(得分:5)

对于Swift 4(和3),请使用:

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

这种方法普遍获得捆绑

答案 5 :(得分:0)

对于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)

我在my project中使用它,它适用于IB和设备。

答案 6 :(得分:0)

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

ToString()