最近做了個需求,需要在對tableview的行進行插入/刪除操作的時候加上飛入飛出動畫。故踩了一下關于beginUpdates和endUpdates的坑,這里記錄一下
beginUpdates
和endUpdates
必須成對使用
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,動畫問題解決了,這些應該完美了吧!事實告訴我,我還是太年輕,beginUpdates
和endUpdates
只會刷新當前顯示的cell,當cell開始重用的時候就出現了一些奇怪的狀況(跟cell定制有關,不一定會有問題),這時候最簡單的方法就是把整個tableVIew reload一遍,可是如果在endUpdates
后面reloadDatas,會把動畫強行終止,所以我需要在插入動畫結束后reloadDatas,stackoverflow發現了一個好東西:
[CATransaction begin]; // 監聽動畫結束回調
[CATransaction setCompletionBlock:^{
// 動畫結束
}];
[self.tableView beginUpdates];
[self.tableView endUpdates];
[CATransaction commit];
簡單的說就是:beginUpdates
和endUpdates
也是一組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高度變高,也可以用beginUpdates
和endUpdates
設置動畫:
[cell showAddView]; // 調用方法計算cell的高度
[self.tableView beginUpdates];
[self.tableView endUpdates];
在這里beginUpdates
和endUpdates
中間不需要插入任何代碼。