How to load an image in prepareForInterfaceBuilder

2019-03-08 11:21发布

I would like to load a sample image in an IB designable UIImageView, to be shown in Interface Builder while editing the interface. The following code does not work, as the view placeholder in IB remains empty (the view area contains only the UIImageView text):

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

Note that:

  • in IB the Custom Class class for the view is correct (TestImageView)
  • Test.jpg is present in the project (if I manually set the image property of the UIImageView in IB the image shows up).
  • I tried the two different methods of getting the bundle present in the code

This was tested with Xcode 6 beta 3.

Update: in both cases the bundle path I get is "/Applications/Temporary/Xcode6-Beta3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays". In that path the image is obviously not present.

7条回答
祖国的老花朵
2楼-- · 2019-03-08 11:28

For Swift 4 (and 3) use this:

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

This approach gets the bundle universally

查看更多
smile是对你的礼貌
3楼-- · 2019-03-08 11:34

I was able to fix the issue getting the Interface Builder project path from the current NSProcessInfoobject. You can then gather the correct path from the IB_PROJECT_SOURCE_DIRECTORIESkey.

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

This technique is described in the WWDC 2014 411 session "What's New in Interface Builder" as suggested by bjhomer in this Apple Developer Forums post.

Moreover, I need to say that it was required to switch to a UIView subclass, because it seems that the appereance of the UIImageViewdoes not change in live views.

查看更多
可以哭但决不认输i
4楼-- · 2019-03-08 11:34

This will load your IB_Designable, or if you have none - the default image.

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

}
查看更多
爷、活的狠高调
5楼-- · 2019-03-08 11:42

Updated for Swift 4.2

When you instantiate an UIImage (with UIImage(named : "SomeName") the app will look for the asset in your main bundle, which works fine usually. But when you are at design time, the InterfaceBuilder holds the code of the designable views (for compiling while designing) in a separate bundle.

So the solution is: Define your bundle dynamically, hence your files can be found in design, compile and run time:

    // 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)
查看更多
甜甜的少女心
6楼-- · 2019-03-08 11:43

Lets pop in the swift 3 answer

let bundle = Bundle(for: self.classForCoder)
... UIImage(named: "AnImageInYourAssetsFolderPerhaps", in: bundle, compatibleWith: self.traitCollection)!
查看更多
Rolldiameter
7楼-- · 2019-03-08 11:49

For Swift 2 and Xcode 7, the interface has been changed. Should use

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

I use it in my project, it works fine for both IB and device.

查看更多
登录 后发表回答