这篇文章就没有效果图了,我在这儿主要说说什么是面向协议的编程,不过是通过一个例子来具体的说明的。
先说说什么是面向对象的编程吧。
class A: NSObject {
var name1: String?
var name2: String?
func dataModels() -> Array<Any> {
return ...
}
}
class B: A {
}
面向对象的编程,说得通俗一点就是对实体的封装化,而这个物体有自己的属性,方法;那么通过继承的属性,其他对象也可以使用被继承对象的一些属性或方法。
但面向对象就会产生一个弊端,就是不能进行多继承,那么这时候就出现了面向协议的编程,当然这是swift才有的。
那么通过一个简单的例子说说吧。
编码场景: 我们常常在控制器中用到的有UITableView
,那么我们可以自定义一个用到这个控件的协议,我们要用的时候,只需要进行简单的初始化。
例如:
class A: UIViewController, RSTableViewProtocol {
private lazy var tableView : UITableView = {
() -> UITableView in
let view = tableViewConfig(.zero, self, self, .plain)
registerCell(view, RSMineCenterCell.self)
return view
}()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : Cell = cellWithTableView(tableView)
return cell
}
}
而我们定义协议的时候只需要:
public protocol RSTableViewProtocol { }
public extension RSTableViewProtocol {
private func configIdentifier(_ identifier: inout String) -> String {
var index = identifier.index(of: ".")
guard index != nil else { return identifier }
index = identifier.index(index!, offsetBy: 1)
identifier = String(identifier[index! ..< identifier.endIndex])
return identifier
}
public func registerCell(_ tableView: UITableView, _ cellCls: AnyClass) {
var identifier = NSStringFromClass(cellCls)
identifier = configIdentifier(&identifier)
tableView.register(cellCls, forCellReuseIdentifier: identifier)
}
public func cellWithTableView<T: UITableViewCell>(_ tableView: UITableView) -> T {
var identifier = NSStringFromClass(T.self)
identifier = configIdentifier(&identifier)
var cell = tableView.dequeueReusableCell(withIdentifier: identifier)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: identifier)
}
return cell as! T
}
public func tableViewConfig(_ frame: CGRect ,_ delegate: UITableViewDelegate, _ dataSource: UITableViewDataSource, _ style: UITableViewStyle?) -> UITableView {
let tableView = UITableView(frame: frame, style: style ?? .plain)
tableView.delegate = delegate
tableView.dataSource = dataSource
tableView.separatorStyle = .none
tableView.showsVerticalScrollIndicator = false
return tableView
}
}
这样我用到这个组件的时候,就很方便了,这样就大大减少了代码的重复写。
当然这是UITableView的协议,这儿我再给出UICollectionView的协议。
public protocol RSCollectionViewProtocol {}
public extension RSCollectionViewProtocol {
private func configIdentifier(_ identifier: inout String) -> String {
var index = identifier.index(of: ".")
guard index != nil else { return identifier }
index = identifier.index(index!, offsetBy: 1)
identifier = String(identifier[index! ..< identifier.endIndex])
return identifier
}
public func registerCell(_ collectionView: UICollectionView, _ cellCls: AnyClass) {
var identifier = NSStringFromClass(cellCls)
identifier = configIdentifier(&identifier)
collectionView.register(cellCls, forCellWithReuseIdentifier: identifier)
}
public func collectionViewConfig(_ delegate: UICollectionViewDelegate,
_ dataSource: UICollectionViewDataSource,
_ layout: UICollectionViewLayout) -> UICollectionView {
let collectionView = UICollectionView.init(frame: .zero, collectionViewLayout: layout)
collectionView.delegate = delegate
collectionView.dataSource = dataSource
collectionView.backgroundColor = .white
return collectionView
}
public func cellWithCollectionView<T: UICollectionViewCell>(_ collectionView: UICollectionView, _ indexPath: IndexPath) -> T {
var identifier = NSStringFromClass(T.self)
identifier = configIdentifier(&identifier)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath)
return cell as! T
}
}
当然用法也是类似的。
lazy var collView : UICollectionView = {
() -> UICollectionView in
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
let _collView = collectionViewConfig(self, self, layout)
registerCell(_collView, RSOrderStatusCell.self)
return _collView
}()
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell : RSOrderStatusCell = cellWithCollectionView(collectionView, indexPath)
return cell
}
这样我们就对什么是面向协议的编程有了基本的了解了。