如何使用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)
这种方法普遍获得捆绑