前言
如果iOS開發(fā)不是直接從Swift開始,那么熟悉OC的大哥們一定都了解OC的Category.
通過Category我們可以封裝該類的工具類方法,使得開發(fā)更有效率.
然而,在Swift中Extension的使用方式可不止這些.它有著更多的用途.
而我從Swift2.0開始接觸這么語言,從OC到Swift中的生搬硬套,到現(xiàn)在的先從Swift這么語言的特點開始編程.這個過程只能說,只有不斷的寫代碼,思考代碼,才能有所收獲.
而對于Extension的使用的啟蒙,我是通過這篇文章開始的,大家也可以看看.也許在這位大神的文章面前,我后面寫的都不過是九牛一毛.
那么下面進入正題,我們?nèi)绾蝺?yōu)雅的使用Extension呢?這里我只說編碼思路與風格,代碼的邏輯大家就將就這看吧.
遵守協(xié)議的時候使用Extension
這是一個很常見的編碼需求.控制器中創(chuàng)建了一個tableView,設置tableView的數(shù)據(jù)源與代理給控制器.
你完全可以這樣進行編碼:
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()
}
}
但是我更建議這樣寫,將數(shù)據(jù)源和代理分別使用一個Extension去進行遵守,這樣雖然代碼行多了點,但是對于分隔業(yè)務與功能是非常清晰的
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可以用于遵守協(xié)議使用,同時建議每遵守一個協(xié)議就另起一個分類,因為Extension的用途之一就是用來分隔不同的業(yè)務
加上再使用//MARK: -
這就是我要的風格
不同的業(yè)務使用Extension
其實上面的遵守協(xié)議使用Extension時我就是用了這條原則
比如我在一個控制器中,有很多不同的業(yè)務邏輯,比如需要進行網(wǎng)絡請求,比如有多個按鈕的點擊事件
那么你可以這么使用Extension,使得代碼在可讀性和可維護性上所有提高
// MARK: - 網(wǎng)絡請求處理模塊
extension ViewController {
}
// MARK: - 按鈕點擊事件的處理模塊
extension ViewController {
}
.
.
.
你可以繼續(xù)按照這個思路去添加Extension去分離不同業(yè)務層.
私有API與對外API使用Extension
同事剛從OC轉(zhuǎn)Swift的時候,經(jīng)常和我抱怨,OC有.h和.m文件,使用類的時候,點擊.h文件就可以很清晰的看到該類的那些API我是可以使用的,而Swift中只有一個.swift文件,不能一眼看出那些是私有API那些是對外API.需要看private 和 fileprivate關鍵字才行.
其實我的建議的是通過Extension進行私有API與對外API的分離.當然這個和不同的業(yè)務使用Extension進行分離有點相違背,不過團隊合作的時候可以約定一個規(guī)則,便于進行風格管理
// MARK: - 私有API
extension ViewController {
}
// MARK: - 對外API
extension ViewController {
}
或者 在 聲明類的這個大括號類全部寫對外API,在Extension中寫私有API
// MARK: - 對外API
class ViewController: UIViewController {
}
// MARK: - 私有API
extension ViewController {
}
使用Extension的注意事項
Extension中不能寫構(gòu)造函數(shù)與析構(gòu)函數(shù),這兩個函數(shù)必須在聲明的class中進行使用
Extension中可以寫便利構(gòu)造函數(shù).
Extension中不能定義屬性,如果非要定義,請使用Runtime的那一套原則
Extension中可以定義只讀計算屬性
Extension到底啥個用法?我也不知道呀
Extension的使用,我可以做一個比較生動的例子
就像火影忍者的影分身之術,每Extension一個,就好像多了一個影分身,而這個影分身去遵守協(xié)議、去實現(xiàn)不同的功能進而這個影分身會有著不同技能,而其本體則可以任意調(diào)用這些技能.
Extension的使用,使得遵守Protocol的變相多繼承變?yōu)榱丝赡?后面有機會會寫如何優(yōu)雅的使用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 {
}