728x90
performBatchUpdates
- UITableView와 UICollectionView에서 insert, delete, reload, move 등의 동작들의 애니메이션을 group화해서 동시에 실행할 수 있게 해주는 메소드이다
- beginUpdates(), endUpdates()와 같이 batch update를 적용할 수 있는 방법 중에 하나이며, 애플 공식문서에서는 beginUpdates(), endUpdates() 대신 performBatchUpdates를 사용할 것을 권장하고 있다.
- 주의사항
- 해당 메서드를 호출하기 전에, TableView 혹은 CollectionView의 레이아웃이 업데이트 되어있지 않다면 reload가 일어날 수 있기 때문에, 이 메서드를 호출하기 전에 항상 레이아웃이 업데이트되어있게 하거나 'updates' block안에서 데이터 모델을 업데이트 해야 한다.
- batch 오퍼레이션에서 delete는 insert가 실행되기 전에 먼저 실행된다. 그렇기 때문에 insert 뒤에 delete를 실행할 때 index는 insert가 되기 전 상황을 기준으로 계산해야 한다. (beginUpdates, endUpdates 사용 시에도 마찬가지)
Parameter | description |
updates | insert, delete, reload, move 오퍼레이션을 실행하는 block이다. |
completion | - 모든 오퍼레이션이 끝나고 실행되는 completion 핸들러 블록이다. - 해당 block은 Boolean 파라미터를 하나 가지고 있는데, 해당 값이 true면 모든 애니메이션이 정상적으로 종료되었다는 뜻이고, false이면 어떤 이유에서든 간에 애니메이션이 정상적으로 완료되지 못했다는 뜻이다. - completion파라미터는 nil이 될 수 있다. |
delete, insert 동시 사용 시 주의
class ViewController: TSViewController {
@IBOutlet weak var tableView: UITableView!
var stringList: [String] = ["Hello", "World"] //시작할 땐 2개의 item
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "TestCell", bundle: Bundle.main), forCellReuseIdentifier: "testCell")
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = UITableView.automaticDimension
tableView.reloadData()
}
@IBAction func performClick(_ sender: Any) {
tableView.performBatchUpdates({
stringList.insert("new", at: 0) //1개의 item을 더 추가해서 dataSource인 stringList의 아이템 개수는 총 3개가 된다.
tableView.insertRows(at: [[0, 0]], with: .fade)
stringList.remove(at: 2)//맨 마지막 index의 아이템을 지운다.
tableView.deleteRows(at: [[0, 2]], with: .fade)// Crash: attempt to delete row 2 from section 0 which only contains 2 rows
})
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "testCell", for: indexPath) as! TestCell
cell.label.text = stringList[indexPath.row]
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
stringList.count
}
}
위에서 설명했듯이 deleteRows가 배치에서 먼저 실행되기 때문에 insert를 코드상에선 먼저 실행하더라도 크래시가 발생한다.
정상적으로 삭제하려면 아래와 같이 작성해야 한다.
tableView.performBatchUpdates({
stringList.insert("new", at: 0) //1개의 item을 더 추가해서 dataSource인 stringList의 아이템 개수는 총 3개가 된다.
tableView.insertRows(at: [[0, 0]], with: .fade)
stringList.remove(at: 2)//맨 마지막 index의 아이템을 지운다.
tableView.deleteRows(at: [[0, 1]], with: .fade)//dataSource에는 3개의 아이템이 존재하더라도 배치상 delete가 먼저 실행되기 때문에 2개의 아이템을 기준으로 삭제할 index를 계산
})
728x90
'iOS > 설명' 카테고리의 다른 글
[iOS] Push Notification callback함수들 (1) | 2022.04.24 |
---|---|
[iOS] UIView.transition (0) | 2022.04.24 |
[iOS] json파일 dictionary로 불러오기 (0) | 2022.04.22 |
[iOS] Bundle (0) | 2022.04.22 |
[iOS] 앱 terminate되게 하는 법 (0) | 2022.04.22 |
댓글