Could not cast value of type UIView to [CustomView] using Xib

◇◆丶佛笑我妖孽 提交于 2020-11-29 10:14:15

问题


I've seen a number of similar questions, but many aren't up-to-date, and none have fixed my issue.

I have a custom Xib and class, CardView. When I try to instantiate it in code, I get Could not cast value of type 'UIView' to 'CardView'.

Class is as follows:

class CardView: NibView {

    @IBOutlet var contentView: UIView!
    @IBOutlet weak var wordLabel: UILabel!
    @IBOutlet weak var flipButton: UIButton!
    @IBOutlet weak var playButton: UIButton!

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

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

    private func commonInit() {
        Bundle.main.loadNibNamed("CardView", owner: self, options: nil)
        addSubview(contentView)
        contentView.frame = self.bounds
        contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]

    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

and NibView is a custom superclass and looks like:

class NibView: UIView {
    var view: UIView!
    override init(frame: CGRect) {
        super.init(frame: frame)

        // Setup view from .xib file
        xibSetup()
    }

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

        // Setup view from .xib file
        xibSetup()
    }
}
private extension NibView {

    func xibSetup() {
        backgroundColor = UIColor.white
        view = loadNib()
        // use bounds not frame or it'll be offset
        view.frame = bounds
        // Adding custom subview on top of our view
        addSubview(view)

        view.translatesAutoresizingMaskIntoConstraints = false
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[childView]|",
                                                      options: [],
                                                      metrics: nil,
                                                      views: ["childView": view]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[childView]|",
                                                      options: [],
                                                      metrics: nil,
                                                      views: ["childView": view]))
    }
}

extension UIView {
    /** Loads instance from nib with the same name. */
    func loadNib() -> UIView {
        let bundle = Bundle(for: type(of: self))
        let nibName = type(of: self).description().components(separatedBy: ".").last!
        let nib = UINib(nibName: nibName, bundle: bundle)
        return nib.instantiate(withOwner: self, options: nil).first as! UIView
    }
}

Here is a screenshot of my file inspector showing that I set the File's Owner custom class to CardView, which seems to be a stumbling block for many

Finally, I try to instantiate the CardView as follows: CardView().loadNib() as! CardView


回答1:


In case someone still having this problem, I have the same problem and I think we follow same tutorial.

You have called loadNib() in your xibSetup(). I think you don't have to call it again.

So instead of using

let myCardView = CardView().loadNib() as! CardView

I just use

let myCardView = CardView()



回答2:


In your UIViewController, when you create an instance of your CardView, instead of casting it like CardView().loadNib() as! CardView, you call the function object_setClass(_, _) to avoid that error (from Xcode 9).

So it should be like:

let myCardView = CardView().loadNib
object_setClass(myCardView, CardView.self)
view.addSubview(myCardView)



回答3:


Old question, but in case anyone's here:

My problem was that the view subclass was fileprivate. IB doesn't like that apparently.




回答4:


For me loading xib programmatically in this way doesn’t work. I had to remove File owner’s class name and set that to the class name of first view. And then I had to set outlets to the components which I’m going to use.

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)!
}
override init(frame: CGRect) {
    super.init(frame: frame)
}

Added to custom view class after outlets. For you it's CardView. Then I loaded that view class like

let viewCard = Bundle.main.loadNibNamed("CardView", owner: self, options: nil)?.first as! CardView
view.addSubview(viewCard)


来源:https://stackoverflow.com/questions/47382566/could-not-cast-value-of-type-uiview-to-customview-using-xib

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!