У меня есть хорошая реализация XibLoadedView, которая позволяет загружать подклассы UIView из xibfile в раскадровки.Однако я хочу иметь возможность повторно использовать эти 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, ни один из inits в XibLoadedView не вызывается.Однако добавление 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.Но он считает себя i XibLoadedView, а не правильным общим подклассом XibLoadedView.
Есть мысли?