问题
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