logo头像
Snippet 博客主题

一行代码搞定下拉刷新和无数据时空白图

下拉刷新依然使用MJRefresh,为了不每一次下拉刷新都写两个方法且重复的数据处理逻辑,给UIScrollView添加一个分类,使用运行时绑定pageNo和pageSize,废话不多说直接上代码

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import UIKit
import MJRefresh

extension UIScrollView {
struct runtimeKey {
static var pageNoKey = UnsafeRawPointer.init(bitPattern: "pageNoKey".hashValue)
static var pageSizeKey = UnsafeRawPointer.init(bitPattern: "pageSizeKey".hashValue)
static var dataSourceKey = UnsafeRawPointer.init(bitPattern: "dataSourceKey".hashValue)

}

var pageNo:Int? {
set{
objc_setAssociatedObject(self, UIScrollView.runtimeKey.pageNoKey!, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
}
get {
return objc_getAssociatedObject(self, UIScrollView.runtimeKey.pageNoKey!) as? Int
}
}
var pageSize:Int? {
set{
objc_setAssociatedObject(self, UIScrollView.runtimeKey.pageSizeKey!, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
}
get {
return objc_getAssociatedObject(self, UIScrollView.runtimeKey.pageSizeKey!) as? Int
}
}

var refreshDataSource:Array<Any>? {
set{
objc_setAssociatedObject(self, UIScrollView.runtimeKey.dataSourceKey!, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
get {
return objc_getAssociatedObject(self, UIScrollView.runtimeKey.dataSourceKey!) as? Array
}
}




var uHead: MJRefreshHeader {
get { return (mj_header ?? MJRefreshHeader.init())! }
set { mj_header = newValue }
}

var uFoot: MJRefreshFooter {
get { return (mj_footer ?? MJRefreshFooter.init())! }
set { mj_footer = newValue }
}

func lf_addHeader(beginRefresh:Bool, block:@escaping LFCallBack){
self.pageSize = 10
self.pageNo = 1

self.uHead = URefreshHeader{[unowned self] in
self.pageNo = 1

block()
}
if beginRefresh {
self.uHead.beginRefreshing()
}
}
func lf_addFooter(block:@escaping LFCallBack){
self.uFoot = URefreshFooter{[unowned self] in
self.pageNo! += 1
block()
}
}

func lf_setRefresh(dataSource:Array<Any>?){
if self.pageNo == 1 {
self.refreshDataSource = dataSource

}else {
self.refreshDataSource? += dataSource ?? []
}

if self.refreshDataSource?.count == 0 {
self.ly_showEmpty()
}else {
self.ly_hideEmpty()
}

self.uHead.endRefreshing()
if dataSource?.count == 0 && dataSource?.count ?? 0 < self.pageSize ?? 10 {
self.uFoot.endRefreshingWithNoMoreData()
}else {
self.uFoot.endRefreshing()
}
}
}

class URefreshHeader: MJRefreshGifHeader {
override func prepare() {
super.prepare()
lastUpdatedTimeLabel?.isHidden = true
stateLabel?.isHidden = true
}
}

class URefreshAutoHeader: MJRefreshHeader {}

class URefreshFooter: MJRefreshBackNormalFooter {}

class URefreshAutoFooter: MJRefreshAutoFooter {}


class URefreshDiscoverFooter: MJRefreshBackGifFooter {

override func prepare() {
super.prepare()
// backgroundColor = UIColor.init(red: 239/255.0, green: 239/255.0, blue: 239/255.0, alpha: 1)
backgroundColor = UIColor.clear
setImages([UIImage(named: "pullToRefresh_0_80x60_")!], for: .idle)
stateLabel?.isHidden = true
refreshingBlock = { self.endRefreshing() }
}
}

class URefreshTipKissFooter: MJRefreshBackFooter {

lazy var tipLabel: UILabel = {
let tl = UILabel()
tl.textAlignment = .center
tl.textColor = UIColor.lightGray
tl.font = UIFont.systemFont(ofSize: 14)
tl.numberOfLines = 0
return tl
}()

lazy var imageView: UIImageView = {
let iw = UIImageView()
iw.image = UIImage(named: "pullToRefresh_0_80x60_")
return iw
}()

override func prepare() {
super.prepare()
// backgroundColor = UIColor.init(red: 239/255.0, green: 239/255.0, blue: 239/255.0, alpha: 1)
backgroundColor = UIColor.clear
mj_h = 240
addSubview(tipLabel)
addSubview(imageView)
}

override func placeSubviews() {
tipLabel.frame = CGRect(x: 0, y: 40, width: bounds.width, height: 60)
imageView.frame = CGRect(x: (bounds.width - 80 ) / 2, y: 110, width: 80, height: 80)
}

convenience init(with tip: String) {
self.init()
refreshingBlock = { self.endRefreshing() }
tipLabel.text = tip
}
}

以上核心代码主要看lf_setRefresh这个方法,包含了数据源处理和空白图的处理
具体使用方法:在控制器中添加两行

1
2
3
4
5
6
tableView.lf_addHeader(beginRefresh: true) {[unowned self] in
self.loadData()
}
tableView.lf_addFooter {[unowned self] in
self.loadData()
}

还没完,需要在loadData方法设置一下数据源,调用lf_setRefresh方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    func loadData() {
HttpRequest.loadData(target: PXSArticleAPI.articleList(page: tableView.pageNo ?? 1, cate: self.cateId ?? 0,title:searchStr ?? ""), success: { (res) in
let json = JSON(res)
let article_list = JSONDeserializer<PXSArticleListModel>.deserializeModelArrayFrom(json: json["data"]["result"]["article_list"].description)

// self.mdataSource = article_list as! Array<PXSArticleListModel>
self.tableView.lf_setRefresh(dataSource: article_list as?[PXSArticleListModel])
self.tableView.reloadData()

}) { (state_code, message) in
self.tableView.uHead.endRefreshing()
self.tableView.uFoot.endRefreshing()
}
}

到这里所以逻辑都完成了,执行给tableView设置数据源的时候通过self.tableView.refreshDataSource?.count获取处理后的数据源

1
2
3
override func numberOfSections(in tableView: UITableView) -> Int {
return self.tableView.refreshDataSource?.count ?? 0
}

写的不好勿喷

微信打赏

赞赏是不耍流氓的鼓励