简体   繁体   中英

Making outlet for the object from a xib file

I am having a Hint.xib file where I have few elements (label, image view and a button). And I have a class called Hint, which is the subclass of a UIView and which loads this xib.

Here is how Hint class implementation looks:

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

Current Setup

On a storyboard, currently, I've added one view controller, and I have dragged a UIView inside of that view controller's view. After that, I set its custom class to Hint . Also I am using @IBDesignable directive and have overriden prepareForInterfaceBuilder() to have everything rendered in design, and this all works until I try to make an outlet for a label ( hintLabel ) that is a part of a Hint.xib file.

I am getting next error:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[< NSObject 0x60000001f8a0 > setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key hintLabel.'

I've selected my Hint.xib file -> File's Owner, and checked if everything is okay in Identity Inspector, and it seems things are fine there:

在此输入图像描述

What would be an appropriate way to change this label's text either through IB or through the code. Also, I can't just change this label's text in Hint.xib, because I might to have multiple views on a screen that load (from) this xib and all of those views should have different text. I think I am missing something obvious here...Thanks for your hints :))

The problem is you have to load xib from bundle with "owner:self" so it should look like this:

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

Also don't forget to set File Owner to Hint class in xib file (not UIView)

What you have is very close to working. The problem is you need to set the owner to the hint view, but you're trying to do that in a class method. self in a class method is the class, whereas you need self to be the instance of the class. Your fromNib method doesn't need to be a class method, it can be an instance method. Here's an example:

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

Now in your view setup, you can use if let view = createView(){ //... } .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM