IOS有些文章不一定是为了上首页投稿

通过 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];
}
上一篇 下一篇

猜你喜欢

热点阅读