SwiftPrtocol-TableViewHeight

一个简单的Swift Protocol应用场景: 通过协议处理TableView的不同数据源

假设有场景是一个列表中有不同类型的数据源,可以任意添加类型(class, enum, struct). 这时使用Protocol可以很好的解决这个问题,同时也可以很方便的去扩展。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
protocol ChinaAnimal {
var totalHeight: CGFloat { get }
}
extension ChinaAnimal { // 默认高度44.0
var totalHeight: CGFloat {
return 44.0
}
}
struct Dogs: ChinaAnimal {
var legs: Int = 4
var totalHeight: CGFloat {
return CGFloat(self.legs * 100)
}
}
class Pigs: ChinaAnimal {
var legs: Int = 4
var totalHeight: CGFloat {
return CGFloat(self.legs * 20)
}
}
enum Cats: ChinaAnimal, RawRepresentable {
typealias RawValue = String
case blue
case white
var totalHeight: CGFloat {
switch self {
case .blue:
return 88.0
case .white:
return 66.0
}
}
init?(rawValue: String) {
switch rawValue {
case "blue":
self = .blue
case "white":
self = .white
default:
self = .blue
}
}
var rawValue: RawValue {
switch self {
case .blue:
return "blue"
case .white:
return "white"
}
}
}

分别构建3个不同的数据结构Class Pigs, Struct Dogs, Enum Cats.

生成数据源

1
2
3
4
5
6
7
8
var sources = [ChinaAnimal]()
//ViewDidLoad
sources.append(Dogs(legs: 4))
let pig = Pigs()
pig.legs = 4
sources.append(pig)
sources.append(Cats.blue)
sources.append(Cats.white)

代理中实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sources.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let animal = sources[indexPath.row]
switch animal {
case let dogs as Dogs:
cell.textLabel?.text = "Dog have \(dogs.legs) legs."
case let pigs as Pigs:
cell.textLabel?.text = "Pig have \(pigs.legs) legs."
case let cat as Cats:
cell.textLabel?.text = "\(cat.rawValue)".capitalized + " cat have \(cat.rawValue) color."
default:
cell.textLabel?.text = nil
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.sources[indexPath.row].totalHeight
}
}


在处理TableView.Height的时候,如果获取高度?可能在不同的Model中有不同的实现。

这里举个例子,将它抽象出来放在协议里面。
如果新增类型的时候,也方便增加,且不会对原Model的数据结构有影响。

可能重构的时候,更能看出使用协议扩展和默认实现的好处了吧😄,很简单。