我們?cè)谛薷腡ableView的數(shù)據(jù)后,經(jīng)常使用下面這句
[self.tableView reloadData];
來(lái)更新UI
但,其實(shí),這里埋了一個(gè)坑,這句代碼執(zhí)行后, 按理說(shuō),應(yīng)該執(zhí)行numberOfRowsInSection
和CellForRow
方法,測(cè)試結(jié)果卻是代碼立即返回,即,整個(gè)過(guò)程是異步的.
多說(shuō)一句,畢竟我們是看不到reloadData
執(zhí)行的源代碼
發(fā)現(xiàn)問(wèn)題
測(cè)試代碼如下:
@IBAction func refresh(_ sender: Any) {
array.removeLast()
print("Reload Begin")
self.tableView.reloadData()
print("Reload End")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("numberOfRowsInSection")
return array.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("cellForRowAt")
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
cell?.textLabel?.text = array[indexPath.row]
return cell!
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
print("heightForRow")
return 44;
}
控制臺(tái)打出的Log如下:
Reload Begin
numberOfRowsInSection
Reload End
cellForRowAt
heightForRow
…
如上所示,調(diào)用reloadData
之后,立即調(diào)用numberOfRowsInSection
,但是cellForRowAt
和heightForRow
是異步調(diào)用,回到當(dāng)前RunLoop,布局cell時(shí)才會(huì)被調(diào)用.
reloadData
這樣的特性就導(dǎo)致了沒(méi)有及時(shí)調(diào)用相對(duì)應(yīng)的代理方法,如果在reloadData
之后,我們想要執(zhí)行某些操作,就會(huì)導(dǎo)致出現(xiàn)不可預(yù)見(jiàn)的結(jié)果.
解決方法
想要調(diào)用reloadData
之后立即調(diào)用所有代理方法,我們可以添加layoutIfNeeded
讓TableView強(qiáng)制布局
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
控制臺(tái)打出的Log如下:
Reload Begin
numberOfRowsInSection
cellForRowAt
heightForRow
…
Reload End
總結(jié)
對(duì)于CollectionView有同樣的問(wèn)題.
針對(duì)這些細(xì)節(jié),只有在平時(shí)的工作學(xué)習(xí)中多總結(jié),在遇到問(wèn)題時(shí),才能更加從?容. 還有,一定善用StackOverFlow等社區(qū)力量,在解決問(wèn)題時(shí)能如虎添翼.