前言
如果iOS开发不是直接从Swift开始,那么熟悉OC的大哥们一定都了解OC的Category.
通过Category我们可以封装该类的工具类方法,使得开发更有效率.
然而,在Swift中Extension的使用方式可不止这些.它有着更多的用途.
而我从Swift2.0开始接触这么语言,从OC到Swift中的生搬硬套,到现在的先从Swift这么语言的特点开始编程.这个过程只能说,只有不断的写代码,思考代码,才能有所收获.
而对于Extension的使用的启蒙,我是通过这篇文章开始的,大家也可以看看.也许在这位大神的文章面前,我后面写的都不过是九牛一毛.
那么下面进入正题,我们如何优雅的使用Extension呢?这里我只说编码思路与风格,代码的逻辑大家就将就这看吧.
遵守协议的时候使用Extension
这是一个很常见的编码需求.控制器中创建了一个tableView,设置tableView的数据源与代理给控制器.
你完全可以这样进行编码:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
view.addSubview(tableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
}
或者这样:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
view.addSubview(tableView)
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
}
但是我更建议这样写,将数据源和代理分别使用一个Extension去进行遵守,这样虽然代码行多了点,但是对于分隔业务与功能是非常清晰的
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
view.addSubview(tableView)
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
}
extension ViewController: UITableViewDelegate {
}
Extension可以用于遵守协议使用,同时建议每遵守一个协议就另起一个分类,因为Extension的用途之一就是用来分隔不同的业务
加上再使用//MARK: -
这就是我要的风格
不同的业务使用Extension
其实上面的遵守协议使用Extension时我就是用了这条原则
比如我在一个控制器中,有很多不同的业务逻辑,比如需要进行网络请求,比如有多个按钮的点击事件
那么你可以这么使用Extension,使得代码在可读性和可维护性上所有提高
// MARK: - 网络请求处理模块
extension ViewController {
}
// MARK: - 按钮点击事件的处理模块
extension ViewController {
}
.
.
.
你可以继续按照这个思路去添加Extension去分离不同业务层.
私有API与对外API使用Extension
同事刚从OC转Swift的时候,经常和我抱怨,OC有.h和.m文件,使用类的时候,点击.h文件就可以很清晰的看到该类的那些API我是可以使用的,而Swift中只有一个.swift文件,不能一眼看出那些是私有API那些是对外API.需要看private 和 fileprivate关键字才行.
其实我的建议的是通过Extension进行私有API与对外API的分离.当然这个和不同的业务使用Extension进行分离有点相违背,不过团队合作的时候可以约定一个规则,便于进行风格管理
// MARK: - 私有API
extension ViewController {
}
// MARK: - 对外API
extension ViewController {
}
或者 在 声明类的这个大括号类全部写对外API,在Extension中写私有API
// MARK: - 对外API
class ViewController: UIViewController {
}
// MARK: - 私有API
extension ViewController {
}
使用Extension的注意事项
Extension中不能写构造函数与析构函数,这两个函数必须在声明的class中进行使用
Extension中可以写便利构造函数.
Extension中不能定义属性,如果非要定义,请使用Runtime的那一套原则
Extension中可以定义只读计算属性
Extension到底啥个用法?我也不知道呀
Extension的使用,我可以做一个比较生动的例子
就像火影忍者的影分身之术,每Extension一个,就好像多了一个影分身,而这个影分身去遵守协议、去实现不同的功能进而这个影分身会有着不同技能,而其本体则可以任意调用这些技能.
Extension的使用,使得遵守Protocol的变相多继承变为了可能,后面有机会会写如何优雅的使用Protocol吧,我用的溜,但是写成文字还有问题
可以试试, viewDidLoad中的两个if方法都是会走的
self is UITableViewDataSource
self is UITableViewDelegate
also self is UIViewController
so, self is what?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
view.addSubview(tableView)
if self is UITableViewDataSource {
print("它是UITableViewDataSource啊")
}
if self is UITableViewDelegate {
print("它是UITableViewDelegate啊")
}
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
}
extension ViewController: UITableViewDelegate {
}