从xib文件中为对象创建插座

时间:2017-01-29 17:27:57

标签: ios swift xcode interface-builder xib

我有一个Hint.xib文件,其中有少量元素(标签,图像视图和按钮)。我有一个名为Hint的类,它是UIView的子类,它加载了这个xib。

以下是Hint类实现的外观:

import UIKit

@IBDesignable

extension UIView {
    class func fromNib<T : UIView>() -> T? {
        guard
            let nibs = Bundle(for: self).loadNibNamed(String(describing: self), owner: nil, options: nil),
            let nib = nibs.first
            else {
                return nil
        }

        return nib as? T
    }
}

class Hint:UIView {
    @IBOutlet weak var hintLabel: UILabel! 
    private func setup(){

        if let view = Hint.fromNib(){
            self.addSubview(view)
            view.frame = self.bounds
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setup()
    }


    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        setup()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

       setup()
    }
}

当前设置

在故事板上,目前,我已经添加了一个视图控制器,并且我在该视图控制器的视图中拖了一个UIView。之后,我将其自定义类设置为Hint。此外,我使用@IBDesignable指令并覆盖prepareForInterfaceBuilder()以使所有内容都在设计中呈现,这一切都有效,直到我尝试为标签(hintLabel)创建一个出口一个Hint.xib文件。

我收到下一个错误:

  

因未捕获的异常终止应用&#39; NSUnknownKeyException&#39;,   原因:&#39; [&lt; NSObject 0x60000001f8a0&gt; setValue:forUndefinedKey:]:this   class不是键值hintLabel的密钥值编码。&#39;

我选择了我的Hint.xib文件 - &gt;文件的所有者,并检查身份检查器中的一切是否正常,看起来一切都很好:

enter image description here

通过IB或代码更改此标签文本的适当方法是什么。另外,我不能在Hint.xib中更改此标签的文本,因为我可能在屏幕上有多个视图来加载(来自)此xib,并且所有这些视图应该具有不同的文本。我想我在这里遗漏了一些明显的东西...感谢您的提示:))

2 个答案:

答案 0 :(得分:3)

问题是你必须从&#34; owner:self&#34;中加载来自bundle的xib。所以看起来应该是这样的:

class Hint:UIView {
    @IBOutlet var view: UIView!
    @IBOutlet weak var hintLabel: UILabel!
    private func setup(){

        Bundle.main.loadNibNamed("Hint", owner: self, options: nil)
        self.addSubview(view)
        view.frame = self.bounds
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setup()
    }


    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        setup()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        setup()
    }
}

也不要忘记在xib文件中设置文件所有者为Hint类(不是UIView)

答案 1 :(得分:3)

你所拥有的是非常接近工作。问题是您需要将所有者设置为提示视图,但您尝试在类方法中执行此操作。类方法中的self是类,而您需要self作为类的实例。您的fromNib方法不需要是类方法,它可以是实例方法。这是一个例子:

extension UIView {
    func createView<T : UIView>() -> T? {
        let type = type(of:self)
        guard
            let nibs = Bundle(for: type).loadNibNamed(String(describing: type), owner: self, options: nil),
            let nib = nibs.last
            else {
                return nil
        }

        return nib as? T
    }
}

现在,在您的视图设置中,您可以使用if let view = createView(){ //... }

相关问题