通过 XIB 自定义 View 的便捷加载方法
2021-10-22 本文已影响0人
韦弦Zhy
虽然 XIB 实现 View 有各种各样的缺点,但是不可否认我们仍然在项目中或多或少的有使用。在加载 XIB 视图的时候每个人都会有自己的封装,今天我从最原始加载方式开始,分享一下我的便捷加载方式是怎么写出来的。
加载通过 XIB 自定义 View 的加载我们一般会有如下方法
XIBView: ZYXIBTestView.xib
在需要使用的 VC:
override func viewDidLoad() {
super.viewDidLoad()
let view = Bundle.main.loadNibNamed("ZYXIBTestView", owner: nil, options: [:])?.last as! ZYXIBTestView
}
或者在XIB对应的view: ZYXIBTestView.swift
中
class func initByNib() -> ZYXIBTestView {
return Bundle.main.loadNibNamed("ZYXIBTestView", owner: nil, options: [:])?.last as! ZYXIBTestView
}
使用的时候:
override func viewDidLoad() {
super.viewDidLoad()
let view = ZYXIBTestView.initByNib()
}
后面我参考我原来写的一个UITableViewCell
的扩展:
extension UITableView {
/// 注册 xib cell
func register<T: UITableViewCell>(nib cellType: T.Type) {
register(UINib(nibName: String(describing: cellType), bundle: nil), forCellReuseIdentifier: String(describing: cellType))
}
/// 复用代码 xib
func dequeueReusable<T: UITableViewCell>(_ cellType: T.Type = T.self, for indexPath: IndexPath) -> T {
guard let cell = dequeueReusableCell(withIdentifier: String(describing: cellType), for: indexPath) as? T else {
fatalError(
"Failed to dequeue a cell with identifier \(String(describing: cellType)) matching type \(cellType.self). "
+ "Check that the reuseIdentifier is set properly in your XIB/Storyboard "
+ "and that you registered the cell beforehand"
)
}
return cell
}
}
写了如下UIView
的扩展:
extension UIView {
class func initNib<T: UIView>(by nibType: T.Type) -> T {
guard let view = Bundle.main.loadNibNamed(String(describing: nibType), owner: nil, options: [:])?.last as? T else {
fatalError(
"Failed to load a view with nibName \(String(describing: nibType)) "
+ "Check that the nibName of your XIB/Storyboard "
)
}
return view
}
}
这个时候无需再 View 中写任何代码,就可以直接使用:
override func viewDidLoad() {
super.viewDidLoad()
let view = ZYXIBTestView.initNib(by: ZYXIBTestView.self)
}
可是看起有点怪怪的,UITableView
复用 Cell 调用是这样的,完全符合使用习惯:
tableView.register(nib: ZTTestCell.self)
···
let cell = tableView.dequeueReusable(ZTTestCell.self, for: indexPath)
···
此时想起了 Self 关键字 可以动态获取引用类型, 所以:
extension UIView {
/// 加载 xib view 类方法
@objc class func initByNib() -> Self {
guard let view = Bundle.main.loadNibNamed(String(describing: Self.self), owner: nil, options: [:])?.last as? Self else {
fatalError(
"Failed to load a view with nibName \(String(describing: Self.self)) "
+ "Check that the nibName of your XIB/Storyboard "
)
}
return view
}
}
此时使用则更符合预期了:
override func viewDidLoad() {
super.viewDidLoad()
let view = ZYXIBTestView.initByNib()
}
同时也支持了OC, 毕竟开始的泛型方法OC是无法调用的:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view = [ZYXIBTestView initByNib];
}