目前市面上的主流 app 毫無疑問的 UI 都是列表,即UITableview 或者 UICollectionView,由于用得多,寫得也多,如果每次實(shí)現(xiàn)一個(gè)列表都要重復(fù)去創(chuàng)建 tableview,然后重復(fù)實(shí)現(xiàn)數(shù)據(jù)源和代理,還要處理多頁加載的問題,WDF 你不嫌累我看著都累,于是,封裝一個(gè)列表屬性的控件非常有必要,在我構(gòu)思中,我的想法是:其實(shí)我們每次做的刷新列表都是一樣的,不一樣的只是 cell 不一樣,因此,最好的方式就是只需要注冊(cè)號(hào)自己的 cell,把數(shù)據(jù)源傳給 DataSource 其他事都可以不用管了。而且,它必須支持自動(dòng)計(jì)算分頁,當(dāng)我先上刷新的時(shí)候會(huì)自動(dòng)計(jì)算頁數(shù),數(shù)據(jù)請(qǐng)求后會(huì)自動(dòng)添加上去,下拉刷新時(shí)會(huì)自動(dòng)請(qǐng)求第一頁的數(shù)據(jù)重新賦值給 DataSource,這樣一來思路就很清晰了。
先看看最終設(shè)置代碼,只需要繼承基類BaseRefreshTableVC,設(shè)置好 cell 類型,然后在refreshData方法里面把網(wǎng)絡(luò)請(qǐng)求下來的數(shù)據(jù)傳給閉包即可:
override func viewDidLoad() {
super.viewDidLoad()
setup(estimatedRowHeight: 100, cell: TestTableViewCell.self)
}
override func refreshData(completionHandler: @escaping ([Any]) -> ()) {
//網(wǎng)絡(luò)請(qǐng)求獲取數(shù)據(jù),pageIndex是基類自動(dòng)計(jì)算好的頁數(shù),直接傳給網(wǎng)絡(luò)請(qǐng)求參數(shù)即可
var data = [""]
for item in 0...pageIndex * 10{
data.append("\(item)")
}
completionHandler(data)
}
接下來說實(shí)現(xiàn)思路。
首先新建一個(gè)基類 BaseRefreshTableVC,里面把該做的初始化 tableview 做好:
tableView.delegate = self;
tableView.dataSource = self;
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
tableView.estimatedRowHeight = 60;
tableView.separatorInset = UIEdgeInsets()
tableView.separatorStyle = .singleLine
tableView.tableFooterView = UIView()
view.addSubview(tableView)
tableView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
接著設(shè)置好頭部刷新和尾部刷新,這里我用得 MJ 的 MJRefresh:
tableView.mj_header = MJRefreshNormalHeader.init(refreshingBlock: {
self.tableView.mj_header.endRefreshing()
self.tableView.mj_footer.endRefreshing()
self.pageIndex = 0;
self.refreshData(completionHandler: { (obj) in
self.dataSource = obj
self.tableView.reloadData()
})
})
tableView.mj_footer = MJRefreshAutoFooter.init(refreshingBlock: {
self.tableView.mj_header.endRefreshing()
self.pageIndex += 1
self.refreshData(completionHandler: { (obj) in
self.dataSource.append(contentsOf: obj)
self.tableView.reloadData()
})
})
大部分場(chǎng)景都是進(jìn)入列表視圖就是自動(dòng)刷新請(qǐng)求數(shù)據(jù),所以在基類加上刷新:
tableView.mj_header.beginRefreshing()
好了,基礎(chǔ)代碼實(shí)現(xiàn)后,接下來看看基類暴露的 api:
public let tableView = UITableView()
public var dataSource = [Any]()
public var pageIndex = 0
public func refreshData(completionHandler: @escaping (_ response:[Any]) ->() ){}
1.暴露 tableview 是為了將來的可擴(kuò)展性,相信項(xiàng)目中不可能只是單純的列表,往往還有什么 header、footer,需要設(shè)置的時(shí)候可以方便設(shè)置。
2.dataSurce,沒什么可說的,比如需要在 didselected 代理方法做事情就可以用到datasouce 內(nèi)容了。
- pageIndex為每次刷新的頁數(shù),默認(rèn)第一頁為0,如果你們項(xiàng)目默認(rèn)是1就自己改成1就可以了。
4.最后refreshData方法是提供給子類實(shí)現(xiàn)的,子類重寫refreshData實(shí)現(xiàn)請(qǐng)求數(shù)據(jù)后吧數(shù)據(jù)傳給completionHandler,基類收到數(shù)據(jù)就會(huì)自動(dòng) reloadData,并且 pageIndex 自動(dòng)?1
最后,說一下 tableviewCell,我也是建議用個(gè) BaseTableViewCell,定義三個(gè)公共方法:
setupViews、setupLayout、configeWithModel分別實(shí)現(xiàn)對(duì) UI控件的初始化創(chuàng)建、約束、和賦值。同理,我也在 baseVC、baseView 中定義了這幾個(gè)通用的方法,以后創(chuàng)建 UI 直接繼承基類,子類實(shí)現(xiàn) setupViews、setupLayout就可以完成子控件初始化,再也不用一個(gè)控制器一種初始化控件方法名,有利于代碼規(guī)范整齊,詳細(xì)看 demo 就可以了。
另外我也寫了個(gè)簡單的分類用來快速創(chuàng)建 UILabel、UIImageView、UIButton
例:
extension UIButton{
public class func cjw_buttonTitle(whit title:String,fontSize:Int,textColor:Int) ->(UIButton){
let btn = UIButton()
btn .setTitle(title, for: .normal)
btn.titleLabel?.font = UIFont.systemFont(ofSize: CGFloat(fontSize))
btn.setTitleColor(UIColor.jk_color(withHex: UInt32(textColor)), for: .normal)
return btn
}
public class func cjw_buttonImage(whit image:String) ->(UIButton){
let btn = UIButton()
btn.setImage(UIImage(named: image), for: .normal)
return btn
}
}
喜歡的可以點(diǎn)個(gè) star,你舉手之勞我會(huì)開心死的,哈哈。
github 地址:(持續(xù)更新)
https://github.com/JW-chenjingwei/BaseObject_Swift