-Today's Learning Content-

  • beginUpdate, endUpdate
  • reloadData, reloadRow

1. TableView Update

개념 정리

UITableViewbeginUpdatesendUpdates라는 메소드를 가지고 있다. 이 메소드들은 테이블 뷰에서 애니메이션과 함께 여러 변경 사항을 한꺼번에 업데이트 할 수 있는 방법을 제공한다.

1) 주요 개념과 역할

beginUpdatesendUpdates는 테이블뷰에서 일어나는 이벤트(셀 삽입, 삭제, 변경 등)를 애니메이션으로 묶어서 처리할 수 있다.

사용 방법은 무척 간단한데, beginUpdatesendUpdates 코드를 작성하고, 그 사이에 셀 삽입, 삭제 등과 같은 테이블뷰 변경 작업을 진행하는 코드를 작성하면 된다.

// 메소드 사용 예시
tableView.beginUpdates()

// 삽입, 삭제, 또는 업데이트 메소드 호출
tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
tableView.deleteRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
tableView.reloadRows(at: [IndexPath(row: 2, section: 0)], with: .automatic)

tableView.endUpdates()

beginUpdatesendUpdates 코드를 사용하면 테이블 뷰에서 여러개의 업데이트가 있을 때, 각 작업마다 테이블 뷰를 새로 고치는 대신 한 번에 묶어서 처리할 수 있기 때문에 성능 면에서 더욱 효율적으로 코드를 작성할 수 있다.

또, beginUpdatesendUpdates 코드를 사용하면 업데이트 중에 테이블 뷰의 데이터 소스와 UI 상태를 동기화 하도록 강제하기 때문에 UI의 일관성을 유지할 수 있다는 장점이 있다.

다만, beginUpdates 호출 전과 endUpdates 호출 후에 데이터 소스는 일관성을 가져야 한다.

2) 사용 사례

새로운 데이터 삽입

func addItem() {
    // 데이터 소스 업데이트
    items.append("새로운 항목")

    // 테이블 뷰 업데이트
    tableView.beginUpdates()
    tableView.insertRows(at: [IndexPath(row: items.count - 1, section: 0)], with: .automatic)
    tableView.endUpdates()
}

데이터 삭제

func removeItem(at index: Int) {
    // 데이터 소스 업데이트
    items.remove(at: index)

    // 테이블 뷰 업데이트
    tableView.beginUpdates()
    tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
    tableView.endUpdates()
}

셀 업데이트

func updateItem(at index: Int, with newValue: String) {
    // 데이터 소스 업데이트
    items[index] = newValue

    // 테이블 뷰 업데이트
    tableView.beginUpdates()
    tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
    tableView.endUpdates()
}

beginUpdatesendUpdates를 사용하는 이점

  • 매끄러운 사용자 경험: UI 업데이트가 애니메이션과 함께 자연스럽게 이루어짐
  • 안전한 데이터 동기화: 데이터 소스와 테이블 뷰 상태 간의 불일치 문제를 방지 가능
  • 유연성: 여러 작업을 일괄 처리할 수 있어 코드가 깔끔하고 유지보수가 비교적 간단함

3) 사용상 주의점

beginUpdatesendUpdates가 정말 좋긴 하지만, 사용할 때 주의해야 할 점이 몇 가지 있다.

  1. 데이터 소스 동기화
    • 변경 작업이 호출되기 전과 후에 데이터 소스의 상태가 테이블 뷰와 일치해야 한다.
    • 예로, 셀을 삽입할 때 데이터 소스 배열에 해당 데이터를 반드시 추가해야 한다.
  2. 배열 인덱스와 일치
    • 변경 작업의 IndexPath가 데이ㅓㅌ 소스 배열의 인덱스와 일치해야 한다.
    • 만약 일치하지 않으면 Crashunsatisfiable constraints와 같은 에러가 발생할 수 있다.
  3. 중첩 금지
    • beginUpdatesendUpdates는 중첩해서 호출할 수 없다.
    • 한 번의 업데이트 블록이 끝난 후 새로 호출해야 한다.

4) 차이점?

지금까지 나는 테이블뷰를 업데이트 할 때 reloadData()reloadRows(at:with:)를 주로 사용해왔다. 이 두 메소드 역시 테이블뷰의 UI를 업데이트 하는 역할인데 어떤 점이 다를까?

지금부터 살짝 알아보도록 하자

1️⃣ reloadData
reloadData는 테이블 뷰 전체를 다시 로드하는 기능이다. 데이터 소스의 변경 사항을 반영하여 모든 섹션과 모든 셀을 다시 생성한다.

// 사용 방법 예시
tableView.reloadData()

이 방법을 사용하면 한 번의 호출로 간단하게 테이블뷰의 UI를 업데이트 할 수 있기 때문에 편리하고, 전체 데이터 소스가 변경될 경우 유용하게 사용할 수 있다.

다만, reloadData는 효율성이 저하되는 단점이 있다. 전체 테이블 뷰를 다시 그리기 때문에 변경된 셀 뿐만 아니라 변경된 점이 없는 셀도 다시 로드하기 때문에 그렇다.

또, 셀 추가나 삭제, 변경 등의 작업을 수행하여도 애니메이션이 제공되지 않기 때문에 부드러운 UI의 변경을 원한다면 부적합하다.
(UIView.animate()메소드를 쓸 수도 있지만 번거롭다.)

게다가 만약 테이블 뷰의 데이터가 많을 경우 불필요한 UI 업데이트로 인해 성능이 저하될 수 있으므로 적절히 상요해야 한다.

2️⃣ reloadRows
reloadRows는 특정 셀만 다시 로드하는 기능이다. 주로 데이터 소스가 일부만 변경되는 경우 사용한다.

// 사용 예시
tableView.reloadRows(at: [indexPath], with: .automatic)

이 방법을 사용하면 필요한 셀만 업데이트하기 때문에 성능 면에서 볼 때 더욱 효율적이다. 또, 기본적으로 애니메이션을 지원하기 때문에 UI 업데이트를 더 부드럽게 구현할 수 있다.

주의할 점은 reloadRows를 쓸 때는 데이터 소스의 상태가 테이블 뷰와 정확히 동기화 되어야 한다. 만약 동기화가 잘못되면 코드가 충돌하거나 비정상적인 동작이 발생할 수 있기 때문에 데이터 소스와의 동기화가 중요하다.

3️⃣ Updates
beginUpdatesendUpdates는 위에서도 설명한 것처럼 여러 변경 사항(셀 삽입, 삭제, 변경 등)을 애니메이션과 함께 그룹화하여 처리하는 기능이다.

// 사용 예시
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: 2, section: 0)], with: .automatic)
tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
tableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
tableView.endUpdates()

이 코드는 애니메이션을 지원하기 때문에 삽입, 삭제, 갱신 등의 작업이 자연스럽게 처리되고, 여러 작업을 한 번에 묶어서 처리할 수 있어서 코드를 더욱 간결하고 구조적으로 작성할 수 있게 된다.
또, 모든 데이터를 업데이트 하는 것이 아니라 필요한 부분만 업데이트 하며, 애니메이션을 자동으로 최적화 해주기 때문에 편리하다.

그러나 beginUpdatesendUpdates를 사용하면 코드가 다소 복잡해질 수 있으며, 데이터 소스와의 일관성을 신경 써야 하기 때문에 불편할 수 있다.

또, 업데이트 작업이 많거나 잘못 설정되면 성능에 부정적인 영향을 미칠 수 있기 때문에 비효율적인 사용을 하지 않도록 주의해야 한다.

4️⃣ 비교 요약

방법업데이트 범위애니메이션성능 효율성사용 시기
reloadData전체 테이블 뷰없음낮음데이터 전체를 새로 고쳐야 할 때, 섹션/셀 변경이 많을 때
reloadRows특정 셀있음중간~높음일부 데이터만 변경할 때, 데이터 소스가 정확히 동기화된 경우
beginUpdates/endUpdates여러 작업(삽입, 삭제, 변경)있음높음여러 변경 작업을 그룹화하여 애니메이션과 함께 처리할 때

5) 각 방법의 사용 예시

reloadData

// 전체 데이터 소스 변경 시
dataArray = ["Item 1", "Item 2", "Item 3"]
tableView.reloadData()

reloadRows

// 데이터 소스의 특정 항목 변경 시
dataArray[0] = "Updated Item"
tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)

updates

// 삽입, 삭제, 갱신 작업을 함께 처리
dataArray.append("New Item")
dataArray.remove(at: 1)
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: 3, section: 0)], with: .automatic)
tableView.deleteRows(at: [IndexPath(row: 1, section: 0)], with: .automatic)
tableView.endUpdates()

각각의 방법은 상황에 따라 알맞게 사용하는 것이 가장 좋으며, 무엇이 뛰어나다고 말할 수 없다.
데이터 변경 크기에 따라 선택하거나, 애니메이션의 여부가 중요하거나, 성능이 중요하거나, 각자 필요한 상황에 적절히 사용하면 된다.


-Today's Lesson Review-

오늘은 개인과제를 수행하며 테이블 뷰에 대해 여러가지 알게된 사실 중 하나인
beginUpdates와 endUpdates에 대해 정리해 보았다.
오늘 공부한 내용을 바탕으로 앞으로는 더욱 효율적인 코드를 작성할 수 있도록 노력해 보려고 한다.
profile
이유있는 코드를 쓰자!!

6개의 댓글

comment-user-thumbnail
2024년 12월 11일

항상 잘 구경?하고 갑니다..ㅎㅎ

1개의 답글
comment-user-thumbnail
2024년 12월 11일

reloadData()만 써보고 이것만 있다고생각했는데 덕분에 지식+1 해서 갑니다~!

1개의 답글
comment-user-thumbnail
2024년 12월 12일

썸네일 매우 킹받네요 저도 테이블 뷰에 다른 기능들이 있다는 걸 알고 갑니다! 성능 효율성이 reloadData보다 좋다는 면에서 쓰고 싶지만 꼼꼼한 코딩이 필요해보이네요🫢

1개의 답글