dev._.note

[Error] NSInternalInconsistencyException 본문

Dev/ERROR

[Error] NSInternalInconsistencyException

Laena 2024. 2. 14. 21:06

원인

테이블뷰에서 스와이프로 삭제버튼을 구현하다가 생긴 에러
삭제는 되지만 시뮬레이터가 멈추고 에러메세지가 출력됨

행을 삭제할 때 내부 일관성 검사에 실패하여 크래시가 발생하는 것으로 이 문제는 일반적으로 테이블 뷰의 데이터 소스에서 행의 수와 테이블 뷰의 UI 상태 사이에 불일치가 있을 때 발생

에러 메세지

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). Table view: <UITableView: 0x140043c00; frame = (0 103; 393 666); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x60000059bb70>; backgroundColor = <UIDynamicSystemColor: 0x600001ecc600; name = tableBackgroundColor>; layer = <CALayer: 0x600000b42180>; contentOffset: {0, 0}; contentSize: {393, 380}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <AlarmButler.AlarmListViewController: 0x13db23550>>'
*** First throw call stack:
(
	0   CoreFoundation                      0x00000001068d5128 __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x0000000105a1412c objc_exception_throw + 56
	2   Foundation                          0x000000010b93263c _userInfoForFileAndLine + 0
	3   UIKitCore                           0x000000011aa716b4 -[UITableView _Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section:] + 92
	4   UIKitCore                           0x000000011aa70f10 -[UITableView _endCellAnimationsWithContext:] + 9676
	5   UIKitCore                           0x000000011aa84fec -[UITableView endUpdatesWithContext:] + 128
	6   UIKitCore                           0x000000011aa85198 -[UITableView _performBatchUpdates:withContext:completion:] + 248
	7   AlarmButler                         0x00000001048d78d8 $s11AlarmButler0A18ListViewControllerC05tableD0_6commit8forRowAtySo07UITableD0C_So0kD16CellEditingStyleV10Foundation9IndexPathVtF + 1468
	8   AlarmButler                         0x00000001048d7f80 $s11AlarmButler0A18ListViewControllerC05tableD0_6commit8forRowAtySo07UITableD0C_So0kD16CellEditingStyleV10Foundation9IndexPathVtFTo + 144
	9   UIKitCore                           0x000000011aaa17ac -[UITableView _animateDeletionOfRowAtIndexPath:] + 116
	10  UIKitCore                           0x000000011aaa81b0 __82-[UITableView _contextualActionForDeletingRowAtIndexPath:usingPresentationValues:]_block_invoke + 48
	11  UIKitCore                           0x000000011a9fd350 -[UIContextualAction executeHandlerWithView:completionHandler:] + 144
	12  UIKitCore                           0x000000011aa086c0 -[UISwipeOccurrence _executeLifecycleForPerformedAction:sourceView:completionHandler:] + 540
	13  UIKitCore                           0x000000011aa08c0c -[UISwipeOccurrence _performSwipeAction:inPullView:swipeInfo:] + 444
	14  UIKitCore                           0x000000011aa09e34 -[UISwipeOccurrence swipeActionPullView:tappedAction:] + 44
	15  UIKitCore                           0x000000011aa110d4 -[UISwipeActionPullView _tappedButton:] + 144
	16  UIKitCore                           0x000000011a87a198 -[UIApplication sendAction:to:from:forEvent:] + 96
	17  UIKitCore                           0x000000011a194e98 -[UIControl sendAction:to:forEvent:] + 108
	18  UIKitCore                           0x000000011a1951dc -[UIControl _sendActionsForEvents:withEvent:] + 268
	19  UIKitCore                           0x000000011a191d1c -[UIButton _sendActionsForEvents:withEvent:] + 120
	20  UIKitCore                           0x000000011a193f18 -[UIControl touchesEnded:withEvent:] + 392
	21  UIKitCore                           0x000000011a3b5458 _UIGestureEnvironmentUpdate + 5912
	22  UIKitCore                           0x000000011a3b3a60 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 288
	23  UIKitCore                           0x000000011a3b37d0 -[UIGestureEnvironment _updateForEvent:window:] + 156
	24  UIKitCore                           0x000000011a8aef00 -[UIWindow sendEvent:] + 3088
	25  UIKitCore                           0x000000011a88e98c -[UIApplication sendEvent:] + 576
	26  UIKitCore                           0x000000011a90f5c0 __dispatchPreprocessedEventFromEventQueue + 1708
	27  UIKitCore                           0x000000011a912474 __processEventQueue + 5524
	28  UIKitCore                           0x000000011a90ae38 __eventFetcherSourceCallback + 156
	29  CoreFoundation                      0x0000000106835f18 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
	30  CoreFoundation                      0x0000000106835e60 __CFRunLoopDoSource0 + 172
	31  CoreFoundation                      0x00000001068355d0 __CFRunLoopDoSources0 + 232
	32  CoreFoundation                      0x000000010682fcb8 __CFRunLoopRun + 768
	33  CoreFoundation                      0x000000010682f5a4 CFRunLoopRunSpecific + 572
	34  GraphicsServices                    0x0000000113b7bae4 GSEventRunModal + 160
	35  UIKitCore                           0x000000011a8752e4 -[UIApplication _run] + 868
	36  UIKitCore                           0x000000011a878f5c UIApplicationMain + 124
	37  UIKitCore                           0x0000000119d283a8 __swift_destroy_boxed_opaque_existential_1Tm + 10284
	38  AlarmButler                         0x00000001048ca5fc $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 120
	39  AlarmButler                         0x00000001048ca574 $s11AlarmButler11AppDelegateC5$mainyyFZ + 44
	40  AlarmButler                         0x00000001048ca6e8 main + 28
	41  dyld                                0x00000001049f1544 start_sim + 20
	42  ???                                 0x0000000104ae60e0 0x0 + 4373504224
	43  ???                                 0x7e57000000000000 0x0 + 9103745171752747008
)
libc++abi: terminating due to uncaught exception of type NSException

 

해결

삭제 작업 후에 테이블 뷰를 업데이트하는 방법을 변경
tableView.reloadData() 사용하여 테이블 뷰를 새로 고침함.

 

수정 전

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // 1. 데이터 모델에서 해당 데이터를 삭제
        let alarmToDelete = viewModel.alarms[indexPath.row]
        viewModel.deleteAlarm(alarmId: alarmToDelete.objectID)
        
        // 2. 뷰 모델에서 해당 알람 뷰 모델 삭제
        viewModel.alarmViewModels.remove(at: indexPath.row)
        
        // 3. 테이블 뷰의 UI를 업데이트
        tableView.performBatchUpdates({
            tableView.deleteRows(at: [indexPath], with: .automatic)
        }, completion: nil)
    }
}

 

수정 후

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // 데이터 모델에서 해당 데이터 삭제
        let alarmToDelete = viewModel.alarms[indexPath.row]
        viewModel.deleteAlarm(alarmId: alarmToDelete.objectID)
        
        // 뷰 모델에서 해당 알람 뷰 모델 삭제
        viewModel.alarmViewModels.remove(at: indexPath.row)
        
        // 테이블 뷰 새로고침
        tableView.reloadData()
    }
}