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

mxb*_*mxb 23 uiimageview ios 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:

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

这是用Xcode 6 beta 3测试的.

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

kas*_*lat 53

尝试获取类的捆绑:

let bundle = NSBundle(forClass: self.dynamicType)
Run Code Online (Sandbox Code Playgroud)

或者像这样指定类名

let bundle = NSBundle(forClass: TestImageView.self)
Run Code Online (Sandbox Code Playgroud)

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

self.image = UIImage("Test", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)
Run Code Online (Sandbox Code Playgroud)

在尝试使用之前,请务必检查您的图像是否为零.我无法使用bundle.pathForResource获取图像路径以正常使用普通图像资源.似乎没有一个UIImage调用,你只指定名称和包,所以你必须使用特征集合.

这个问题与以下内容有关:

xcode 6 IB_DESIGNABLE-不在"接口"构建器中从bundle中加载资源

Apple的回复......

Engineering已确定此问题的行为基于以下内容:

我们无法真正做到这一点比指定捆绑更容易.你可能会说,"哦,让我们调侃 - [NSBundle mainBundle]",但很多引用捆绑的呼叫站点都没有通过那里(或通过CF API).有人可能会说"好吧,那么我们至少要调整一下 - [UIImage imageNamed:]".这里的问题是主捆没有单一的替代品.您可能会同时加载多个实时视图包(框架或应用程序),因此我们不能只选择一个作为主要包.

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

  • 我提供了捆绑示例,因为我向Apple发布了一个错误报告(17656550),因为无法在Live View中找到资源.我在回答中添加了Apple的回复. (3认同)

Luk*_*ker 21

针对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)
Run Code Online (Sandbox Code Playgroud)


Rya*_*TCB 7

让我们快速回答3

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


mxb*_*mxb 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
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个Apple开发者论坛帖子中,bjhomer建议的WWDC 2014 411会话"Interface Builder中的新功能"中描述了这种技术.

而且,我需要说它需要切换到一个UIView子类,因为它的外观似乎UIImageView在实时视图中不会改变.


Jak*_*lář 5

对于Swift 4(和3)使用此:

let image = UIImage(named: "foo", in: Bundle(for: type(of: self)), compatibleWith: traitCollection)
Run Code Online (Sandbox Code Playgroud)

这种方法普遍得到了捆绑