UITableView中的beginUpdates和endUpdates

最近做了個需求,需要在對tableview的行進行插入/刪除操作的時候加上飛入飛出動畫。故踩了一下關于beginUpdates和endUpdates的坑,這里記錄一下
beginUpdatesendUpdates必須成對使用

self.tableView beginUpdates;
// 操作數據源
// 設置要插入/刪除的位置
// 調用插入/ 刪除方法
self.tableVIew endUpdates;

如:

[self.tableView beginUpdates];
[self.dataSource insertObject:model atIndex:indexPath.row]; // 更新數據源
NSMutableArray *indexPaths = [[NSMutableArray alloc]init];
[indexPaths addObject:indexPath]; // 確定要插入的位置
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight]; // 調用插入方法
[self.tableView endUpdates];

寫到這里以后本以為可以一帆風順的實現動畫效果,可是我太年輕了,動畫沒生效!我當時就懵逼了,這不符合道理了,馬上全世界爬技術貼、問答帖,依然無解。經過一番排查,發現問題所在,一個小馬虎而已,希望有相似問題的朋友也長個心眼。

我是將這段代碼放在自己寫的一個delegate回調中的,中間用到的model、indexPath等數據都由delegate傳回,我是在另一個界面dismiss前調用的delegate方法

[self.delegate didFinishEditParagraphWithCell:self.cell text:self.textView.attributedText.string model:self.model andIndexPath:self.cell.indexPath];
[self dismissViewControllerAnimated:YES completion:nil];

分析的結果是:插入動畫執行了,在EditParagraph界面dismiss之前就執行了,所以它就完美地被遮擋了,當EditParagraph界面dismiss后就懵逼地看著動畫結束后的tableView。

所以,找到問題后只需要稍微調整一下代碼:

[self dismissViewControllerAnimated:YES completion:^{
        [self.delegate didFinishEditParagraphWithCell:self.cell text:self.textView.attributedText.string model:self.model andIndexPath:self.cell.indexPath];
    }];

ok,動畫問題解決了,這些應該完美了吧!事實告訴我,我還是太年輕,beginUpdatesendUpdates只會刷新當前顯示的cell,當cell開始重用的時候就出現了一些奇怪的狀況(跟cell定制有關,不一定會有問題),這時候最簡單的方法就是把整個tableVIew reload一遍,可是如果在endUpdates后面reloadDatas,會把動畫強行終止,所以我需要在插入動畫結束后reloadDatas,stackoverflow發現了一個好東西:

[CATransaction begin];  // 監聽動畫結束回調
    [CATransaction setCompletionBlock:^{
    // 動畫結束
    }];
    [self.tableView beginUpdates]; 
    [self.tableView endUpdates];
[CATransaction commit];

簡單的說就是:beginUpdatesendUpdates也是一組CATransaction事務。這樣就可以拿到動畫結束的Block,reload我的tableView啦。

[CATransaction begin];  // 監聽動畫結束回調
    [CATransaction setCompletionBlock:^{
        [self.tableView reloadData];
    }];
        
    [self.tableView beginUpdates];
    [self.dataSource insertObject:model atIndex:indexPath.row];
    NSMutableArray *indexPaths = [[NSMutableArray alloc]init];
    [indexPaths addObject:indexPath];
    [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
    [CATransaction commit];

還有一點值得提的是:如果不需要進行插入和刪除操作,僅僅是改變cell的高度,如點擊cell后,被點擊的cell高度變高,也可以用beginUpdatesendUpdates設置動畫:

[cell showAddView]; // 調用方法計算cell的高度
[self.tableView beginUpdates];
[self.tableView endUpdates];

在這里beginUpdatesendUpdates中間不需要插入任何代碼。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容