自定义view的加载方式有loadNibNamed或者nib.instantiate但是这些都不能使xib直接在storyboard上直接使用。
本文分享出可以在storyboard上直接把xib显示出来,也可以直接用代码加载出来的技能。接下来放大招啦!
1. 新建一个UIview,再建一个xib与之名称对应。
2. 绑定xib的File‘s Owner 的class,注意不是选中View,而是File‘s Owner。
3. 在view中开始代码初始化如下:
override init(frame: CGRect) {
super.init(frame: frame)
initFromXib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initFromXib()
}
func initFromXib() {
let myclass = type(of: self)
let bundle = Bundle(for: myclass)
let name = NSStringFromClass(myclass).components(separatedBy: ".").last
let nib = UINib(nibName: name!, bundle: bundle)
self.contentView = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
self.contentView.frame = bounds
self.addSubview(contentView)
}
每次都要这样写是不是有点麻烦呢?
扩展一个协议NibLoadable,把initFromXib()里面的这段放在协议里。像这样
extension Nibloadable where Self : UIView {
static func loadNibView(className: Self) -> UIView {
let myclass = type(of: className)
let bundle = Bundle(for: myclass)
let name = NSStringFromClass(myclass).components(separatedBy: ".").last
let nib = UINib(nibName: name!, bundle: bundle)
return nib.instantiate(withOwner: className, options: nil)[0] as! UIView
}
}
那么initFromXib()就变成这样,是不是更简化了也用上了swift的协议
func initFromXib() {
self.contentView = CustomXibView.loadNibView(className: self)
self.contentView.frame = bounds
self.addSubview(contentView)
}
然而还不够,这些没次创建view都需要重复写,在加上@IBInspectable的属性就更多,不行我还想简化。继承思想来一波,写一个基础View把所有的属性都写在这里以及初始化方法也都写在这里。自定义view继承它,只需要对外提供一个model变量,来设置内容更改就行。
// 基础view
@IBDesignable
class CGBaseView: UIView, Nibloadable
// 这里是自定义view部分
class TestXibView: CGBaseView {
var model: [String: String]? {
didSet {
desL.text = model?["des"]
}
}
看文章还不够详细,那来开代码吧!附上github地址:https://github.com/caoge9/CG_CustomXibView.git