SwiftUI Table View is Crashing

Hey, I was testing my application and it was crashing while populating the table view. The error code is given below.


2020-03-06 11:57:04.717485-0500 SkiinHeat[945:626193] [TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x105968000; baseClass = UITableView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x282a86f70>; layer = <CALayer: 0x28247cda0>; contentOffset: {0, 0}; contentSize: {0, 88}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <_TtGC7SwiftUIP10$1d350e2b419ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS2___: 0x104abb640>>

2020-03-06 11:57:04.718056-0500 SkiinHeat[945:626193] *** Assertion failure in -[_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView _Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore/UIKit-3901.4.2/UITableView.m:2407

2020-03-06 11:57:04.718307-0500 SkiinHeat[945:626193] *** 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 (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

*** First throw call stack:

(0x19d132a48 0x19ce59fa4 0x19d034e88 0x19d46a6c4 0x1a1355bc4 0x1a1355680 0x1a136c5cc 0x1a136c78c 0x1a136c8ec 0x1d3116020 0x1d31161bc 0x1d31187c8 0x1d3116f38 0x1d3487d90 0x1d3183d44 0x1d317e4f8 0x1d3184ff8 0x1c7c2272c 0x1c7c0b044 0x1c7c0b308 0x1c7c0fff0 0x1d3053d70 0x1d3053b28 0x1d30537c8 0x1d3053920 0x1d336942c 0x1d30538ec 0x1d30710e8 0x1d2edde9c 0x1d2edde04 0x1d2eddf14 0x19d0afe68 0x19d0aad54 0x19d0ab320 0x19d0aaadc 0x1a7030328 0x1a11a5ae0 0x1040d28c0 0x19cf34360)

libc++abi.dylib: terminating with uncaught exception of type NSException.


Can you please guide me on how to handle this exception.



Thanks in Advance

Replies

The cause of crash is probably


_Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section

Confirmed by:

invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'


Check if the number of rows in tableView and in dataSource are consistent. Problem problem comes when you add or remove an element in tableView and forget to update dataSource accordingly.

  • OP mentioned SwiftUI. Do we have a way to confirm the rows in tableView and dataSource? I don't see that way.

Add a Comment
I can confirm that I see the same thing on large List views on MacOS. Doesn't happen on iOS.

The suggestion from Claude31 doesn't help the programmer in this case, since the bug is happening in SwiftUI and the underlying TableView code is being done by the SwiftUI framework.
Confirmed, it happens in iOS 13.3 as well. Trying to switch between several tabs which contains list view and modify the list onAppear will trigger this kind of error.
Unfortunately still having this issue in iOS 14.5. Appears to be some kind of race condition.

Applying .id(UUID()) onto List{} solves the issue by forcing a new @FetchRequest, but also resets the view in case of any ObservedObject changes (... so not really practical solution).
Same problem in iOS14.5 exist some workaround? Some advice for prevent this issue?
Problem also appears when rendering a optional field inside a form section in iOS 14.5
Code Block swift
Form {
Section(header: Text("Details")) {
if showMeasurementField {
HStack {
TextField("\(workoutType.rawValue)", text: $measurement)
.keyboardType(.decimalPad)
Text(workoutTypeUnit!.symbol)
}
}
Stepper("\(sets) set\(sets == 1 ? "" : "s")", value: $sets, in: 1...1000)
Stepper("\(reps) rep\(reps == 1 ? "" : "s")", value: $reps, in: 1...1000)
DurationInput(seconds: $duration)
}
}|


facing same issue 14.5.1. Is there any workaround to fix that ?

Still occurring on random occasions in iOS 14.6 in several separate views using code:

struct FilteredListView: View {
    @EnvironmentObject var numberState: NumberState

    @FetchRequest
    var numbers: FetchedResults<Purging>

    private var downloadCompletePublisher = NotificationCenter.default
        .publisher(for: .dataDownloadComplete)
        .map { notification in
            return notification.userInfo as! [DataSources.Source : Int]
        }
       .receive(on: RunLoop.main)

    var body: some View {    
        List {
            ForEach(Array(numbers.enumerated()), id: \.element.uuid) { index, number in
                NavigationLink(destination: NumberDetailView(number: number)) {
                    NumberRowView(number: number)
                }
            }
        }
        .add(SearchBar(searchText: $numberState.searchText, "Search for N-numbers"))
        .id(numberState.refreshID)      // <-- removing this seems to eliminate the issue 
        .onReceive(downloadCompletePublisher) { userInfo in
            checkForUpdatedNumbers(userInfo: userInfo)
        }
    }

    init(sorter: NumberSorter) {
        ...  code to execute fetch request into _numbers
    }
}

obviously, we don't have access to the UITableView data source methods, but I'd like to know how to peek into SwiftUI's execution.

I had this error when loading data to drive a TabView in .onAppear. I put the load in a DispatchQueue.main.async {} wrapper and the error went away. Looks like it could be happening when structure driving the TabView is being updated when not on the UI thread.

  • This is right,

    When I tried to update the list in .onReceive with notification, it happens,

    AFAIK, notification comes with not main thread, so it should be wrapped with DispatchQueue.main.async

Add a Comment