我有一个很好的XibLoadedView实现,可以将xibfile中的UIView子类加载到Storyboard中。但是我希望能够重用这些xibfiles并从代码中以一般方式加载它们。它似乎不起作用。
@IBDesignable
class XibLoadedView: UIView {
var loadedView: UIView?
required init(fileName: String) {
super.init(frame: .zero)
xibSetup(fileName: fileName)
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup(fileName: String? = nil) {
guard let loadedView = viewLoadedFromNib(named: fileName ?? xibName) else {
return
}
loadedView.frame = bounds
loadedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
setupView()
addSubview(loadedView)
self.loadedView = loadedView
self.backgroundColor = .clear
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setupView()
}
internal func setupView() {
// To be overridden
}
internal var xibName: String? {
// To be overridden if xib filename is other than subclass name
return nil
}
}
具有UIView扩展名:
func viewLoadedFromNib<View: UIView>(named nibName: String? = nil) -> View? {
let nibName = nibName ?? String(describing: type(of: self))
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: nibName, bundle: bundle)
let views = nib.instantiate(withOwner: self, options: nil)
let view = views.first as? View
return view
}
我现在想从代码实例化特定的XibLoadedView子类。就我而言,来自UITableViewCell:
class ViewWrappedTableViewCell: UITableViewCell {
var rootView: UIView!
var cellModel: CellModel!
func setup<View: XibLoadedView>(from cellModel: CellModel, type: View.Type) {
self.cellModel = cellModel
let view = View(fileName: cellModel.xibName)
contentView.addSubview(view)
view.addConstraints(matchingParent: contentView)
if let tableViewWidth = tableView()?.frame.width {
view.addWidthConstraint(width: tableViewWidth)
}
contentView.backgroundColor = .clear
if let view = view as? CellModelSetupable {
view.setup(from: cellModel)
}
self.rootView = view
contentView.layoutIfNeeded()
}
CellModel
存储要实例化的类型(XibLoadedView子类):
class CellModel {
// ...
var viewType: XibLoadedView.Type
问题似乎与此类似:https://stackoverflow.com/a/26284281/511299
如果我不添加必需的init,则XibLoadedView中的所有init均不会被调用。但是,添加required init(fileName: String)
确实会使它在nib.instantiate(withOwner: self, options: nil)
上崩溃,并显示错误:
[<GoodMorning.XibLoadedView 0x7fe5fd1297d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key bottomSeparatorView.'
这是正确的xibfile中的出口。但是它认为自己是XibLoadedView,而不是XibLoadedView的正确泛型子类。
有什么想法吗?