Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] UITableView의 delete 취소 후 바로 move할 때의 버그 해결방법 (편집모드 move 버그) 본문

iOS 응용 (swift)

[iOS - swift] UITableView의 delete 취소 후 바로 move할 때의 버그 해결방법 (편집모드 move 버그)

jake-kim 2023. 5. 20. 23:32

UITableView 편집 모드

  • UITableView의 편집모드 중 Delete와 move관련 개념은 이전 포스팅 글 참고
 

[iOS - swift] UITableView의 편집모드 사용 방법 (셀 삭제, 셀 이동, canEditRowAt, editingStyleForRowAt, commit, can

셀 삭제 기능 활성화 방법 UITableView의 편집모드 중 셀 삭제 - UITableView에서 아무것도 설정 안하고 수정모드에 들어가면 UI는 모두 활성화 버튼에서 tap()이 눌렸을 때 tableView.setEditing(animated:)로 편

ios-development.tistory.com

예제에 사용될 starter project 링크

UITableView의 편집모드 버그

  • 편집모드 진입 > -버튼을 누르면 오른쪽에 Delete 버튼 등장 > 다른곳을 탭하여 취소하게끔하고 오른쪽으로 delete버튼이 들어가는 애니메이션이 끝나기 바로 직전에 long press를 하여 move를 하면 버그가 발생
  • 버그 내용
    • long press가 되었고 move할 준비가 되었는데, 이 때 Delete버튼이 오른쪽으로 다 들어가면 move가 자동으로 확 튀는 현상 발생
    • move가 멈춰있고 다른 버튼을 누르면 크래시도 발생

버그 발생: Delete 버튼이 오른쪽으로 들어가는 동시에 long press 시도

해결 방법

  • Delete 버튼이 오른쪽으로 들어가자마자 cell을 reload 시켜서 long press가 잡혀있더라도 풀리도록 하여 해결이 가능
  • Delete가 들어가는 순간 이벤트를 알아야하는데, 따로 델리게이트가 없으므로 직접 계산이 필요
    • 본인 뷰 및 subview들의 업뎃이 완료되고 호출되는 layoutSubviews()에서 확인이 가능
    • 셀의 layoutSubviews를 관찰해야하므로, Cell을 커스텀하여 생성
final class MyTableViewCell: UITableViewCell
  • frame의 x좌표를 관찰하여, -버튼이 생길때는 x좌표가 음수값이 되고, 다시 Delete버튼이 들어가면 0으로 돌아오기 때문에 이 값을 활용
    • 이 타이밍을 캐치하여 뷰컨에 delegate로 알려주기
protocol MyCellDelegate: AnyObject {
    func willDisapperDeleteButton(index: Int)
}

override func layoutSubviews() {
    super.layoutSubviews()
    defer { lastMinX = frame.minX }
    guard deleteButtonDisappeared, let index else { return }
    delegate?.willDisapperDeleteButton(index: index)
}

weak var delegate: MyCellDelegate?
private var index: Int?
private var lastMinX = 0.0
private var deleteButtonDisappeared: Bool {
    lastMinX < 0 && 0 <= frame.minX
}
  • 뷰컨에서는 이 델리게이트를 통해 값을 받아서 해당 셀만 reloadRow()하면 완료
    • 주의) reloadRow의 애니메이션을 .right로 하면 버그가 있으므로 fade로 할 것
extension ViewController: MyCellDelegate {
    func willDisapperDeleteButton(index: Int) {
        DispatchQueue.main.async {
            self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .fade)
        }
    }
}

cf) 위처럼 reload 하여 해결할 수 있지만, willDisappeareDeleteButton 타이밍에 tableView의 isUserInteractionEnabled를 false로 하고, 버튼이 사라지고 난 후에 isUserInteractionEnabled를 다시 true로 하는 방법도 존재 (이 타이밍을 알려면 Delete버튼을 커스텀해야 하는데, 이 내용은 이 포스팅 글 참고)

 

* 전체 코드: https://github.com/JK0369/ExTableViewEditingBug

Comments