扬庆の博客

Swift从快速加载xib理解 POP

字数统计: 791阅读时长: 3 min
2021/03/19 Share

面相协议编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 举一个例子
protocol Drawing {
mutating func addEllipse(rect: CGRect, fill: UIColor) // 添加椭圆
mutating func addRectangle(rect: CGRect, fill: UIColor) // 添加长方形
}

extension CGContext: Drawing {
func addEllipse(rect: CGRect, fill: UIColor) {
setFillColor(fill.cgColor)
fillEllipse(in: rect)
}
func addRectangle(rect: CGRect, fill fillColor: UIColor) {
setFillColor(fillColor.cgColor)
fill(rect)
}
}

上面代码给CGContext扩展了两个协议方法

作用

  1. 可以当做代理使用
  2. 让结构体/枚举满足协议
  3. 通过协议的 extension 来满足协议添加新方法.
  4. 协议允许我们动态派发.
  5. OC 中共享代码通常使用继承, swift 中可以通过使用协议共享代码.
  6. 可以为类添加协议达到功能点整合.

快速实例化 Xib

xib 是可视化快速创建 UIVIew 的方法

好处不言而喻肯定是方便快速, 通过拖动控件到画布上, 可视化布局, 就能快速搭建想要的界面.

如何能在控制器中快速实例化去管理这个 view呢?

xib 自定义 view 的时候我们通常会用到swift 的接口:

1
let xibView = Bundle.main.loadNibNamed("xibViewClassName", owner: nil, options: nil)?.first as! XibView

单看一行代码, 不算多,一行. 宏观整个项目来说, view 几乎是每个界面都会有,xib 自定义的 view 也会有很多, 这个时候如果采用面相协议+泛型的思路会简单很多,省去了很多重复代码.


???

这里面相协议编程符合哪些条件了呢?

1.类型确定一致是 UIView,无非是不同的自定义 view

2.做的事情是类似的,都是声明实例变量添加父视图

1
Bundle.main.loadNibNamed("xibViewClassName", owner: nil, options: nil)?.first as! xibView

实际我们是想一句话就能实例 xib 对象: let xibView = XibView.loadFromNib()

伪代码协议怎么去表述上面的代码呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protocol xibLoadProtocol { }

extension xibLoadProtocol {
static var nibName: String = "XibView"
static var loadFromNib: Self {
return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil).first as! XibView
}
}

// xib view 只要继承这个协议, 丰富自定义 view 的功能:具有直接调用 loadFromNib 就能实例化变量的方法

class XibView: UIView,xibLoadProtocol {
// some initialize code
}

class SomeViewController: UIViewController {
// initialize xibView
let xibView = XibView.loadFromNib()
}

Result

给所有 UIView 增加了快速加载 xib的功能:

  1. 通过 View 类直接获取 nibName

  2. 直接通过类名获取一个该UIView类实例化对象 loadFromNib

全代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*一般都会写到某些新建的 swift 文件工具类里面*/

// 声明协议
protocol XibLoadProtocol { }

// Where 表示该协议只能被 UIView 继承
extension XibLoadProtocol where Self: UIView {

static var nibName: String {
return String(describing: self)
}
// :Self 表示对象类型是Self 指向的 View(比如 TopView,那么调用后返回的就是 TopView的实例对象)
static var loadFromNib: Self {
return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil)?.first as! Self
}
}


/*项目里如何使用的?*/

// 自定义 View,继承这个协议
class SomeXibView: UIVIew,XibLoadProtocol {
// code
}

// 控制器里直接通过类名的新增快速加载 xib 功能调用
class someViewController: UIViewController {
let xibView = SomeXibView.loadFromNib()
..
view.addSubView(xibview)
}

总结

继承该协议, 就能直接通过类方法, 快速创建 xib 的实例变量.

CATALOG
  1. 1. 面相协议编程
    1. 1.1.
    2. 1.2. 作用
    3. 1.3. 快速实例化 Xib
    4. 1.4. ???
      1. 1.4.1. 伪代码协议怎么去表述上面的代码呢?
    5. 1.5. Result
      1. 1.5.1. 全代码
    6. 1.6. 总结