需求
- 一個(gè)controller中包含一個(gè)tableview和兩個(gè)button,點(diǎn)擊button,tableview進(jìn)行下拉刷新;
- 一個(gè)controller中包含一個(gè)collectionview和兩個(gè)button,點(diǎn)擊button,collectionview進(jìn)行下拉刷新。
實(shí)現(xiàn)
使用Swift3.0語法,使用第三方框架MJRefresh(3.0.8版本)進(jìn)行實(shí)現(xiàn)。
代碼
在按鈕的點(diǎn)擊事件中判斷,是否正在進(jìn)行刷新,如果正在進(jìn)行下拉刷新,則先停止下拉刷新,在開啟下拉刷新。
代碼截圖如下:




效果


問題
從截圖中的動(dòng)畫效果和打印結(jié)果來看,在tableview中,正在刷新時(shí),點(diǎn)擊按鈕,先停止了刷新,然后又開啟的刷新,運(yùn)行結(jié)果符合預(yù)期。但是在collectionview中,正在刷新時(shí),點(diǎn)擊按鈕,直接停止了刷新,并沒有開啟新的刷新,運(yùn)行結(jié)果不符合預(yù)期。
為什么同一個(gè)框架,效果不一樣呢?
探索
這個(gè)地方,我們用到了框架提供的是三個(gè)方法:
mj_header.isRefreshing()
mj_header.beginRefreshing()
mj_header.endRefreshing()
經(jīng)過查看這三個(gè)方法相關(guān)的源碼,我們發(fā)現(xiàn):

在endRefreshing的方法中,進(jìn)行了判斷,如果是UICollectionView,endRefreshing的動(dòng)作延遲了0.1秒執(zhí)行(為什么要延遲0.1s執(zhí)行?),所以我們大膽的猜想,正是由于延遲了這0.1秒,導(dǎo)致collectionView先結(jié)束再刷新實(shí)際執(zhí)行是先刷新了兩次,然后在結(jié)束。如果第二次刷新也延遲0.1秒執(zhí)行,應(yīng)該可以得到正確的結(jié)果。
修改后的代碼:

修改后的結(jié)果:

可以看到,延遲執(zhí)行后,實(shí)際效果和預(yù)期效果相同了。
結(jié)論
在MJRefresh(3.0.8版本)中之所以出現(xiàn)上述問題,是由于框架在endRefreshing的方法中,進(jìn)行了判斷,如果是UICollectionView,endRefreshing的動(dòng)作延遲了0.1秒執(zhí)行,導(dǎo)致了上述問題的產(chǎn)生。所以只要再次刷新時(shí)同樣延遲0.1秒執(zhí)行beginRefreshing()就可以解決問題。
拓展
目前MJRefresh的最新版本為3.1.12,我們來看看在3.1.12版本中這個(gè)問題有什么變化。

在這個(gè)版本中,endRefreshing統(tǒng)一添加到主線程異步執(zhí)行。所以我們的代碼也應(yīng)該把第二次beginRefreshing添加到主線程異步執(zhí)行:

思考
從這兩個(gè)版本的變化中可以看出,3.0.8中的處理是個(gè)臨時(shí)方法,最終的處理方法是3.1.12中添加到主線程異步執(zhí)行。
在我的經(jīng)驗(yàn)中,添加的主線程異步執(zhí)行,解決了在一個(gè)動(dòng)畫未執(zhí)行完畢時(shí)又添加一個(gè)動(dòng)畫導(dǎo)致沖突的問題。所以猜想作者可能是為了解決正在刷新的動(dòng)畫或者用戶對(duì)scrollview進(jìn)行操作的動(dòng)畫和結(jié)束刷新的動(dòng)畫造成沖突。