SwiftUI App crashing on iOS 14 - ContiguousArrayBuffer.swift

We are seeing a huge number of crashes coming from our iOS 14 users with the error Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift, line 444

Following the stack I can see there is no array involved on my side and it actually appears to be a consequence of a setter on a @Published property.

The crash happens only on iOS 14.0 and iOS 14.0.1, while we don't have reports from our iOS 13 users, and it's not systematic, I'd say it happens 3 out of 10 times.

Can anyone please help me debug this issue?

Can you post a full Apple crash report for this? Please use a text attachment to avoid clogging up the timeline.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Hi

I think we're having the same issue, did you find a solution ?

Our app is crashing (100% repro) on an iPhone 11 with iOS 14.0.0 (18A373). Alas I can't debug directly the app on this iPhone.
The crash happens when using a SwiftUI binding to go back in a NavigationView from a screen containing a picker. My guess is that picker is kept around for the duration of the animation but it's data is destroyed leading to a out of range when refreshing it's datasource.

Note that this trace doesn't contain any line of our code, the crash happens in SwiftUI / UIKit.

side note: the website refuse that I upload my trace as a txt file as you suggested to I'll paste it here.

Code Block
Crashed: com.apple.main-thread
0 libswiftCore.dylib 0x1ae6035b8 closure #1 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 384
1 libswiftCore.dylib 0x1ae602ac4 _assertionFailure(_:_:file:line:flags:) + 472
2 libswiftCore.dylib 0x1ae5e0e94 _ArrayBuffer._checkInoutAndNativeTypeCheckedBounds(_:wasNativeTypeChecked:) + 212
3 libswiftCore.dylib 0x1ae5e74d8 Array.subscript.read + 160
4 libswiftCore.dylib 0x1ae5e740c protocol witness for Collection.subscript.read in conformance [A] + 68
5 SwiftUI 0x1b180f1e8 CoreCoordinator.pickerView(_:viewForRow:forComponent:reusing:) + 884
6 SwiftUI 0x1b180f3a4 @objc CoreCoordinator.pickerView(_:viewForRow:forComponent:reusing:) + 100
7 UIKitCore 0x1ad3861f8 -[UIPickerView tableView:cellForRowAtIndexPath:] + 560
8 UIKitCore 0x1ad37c584 -[UIPickerColumnView tableView:cellForRowAtIndexPath:] + 168
9 UIKitCore 0x1ad619580 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 644
10 UIKitCore 0x1ad5e5eac -[UITableView _updateVisibleCellsNow:] + 2476
11 UIKitCore 0x1ad603a90 -[UITableView layoutSubviews] + 356
12 UIKitCore 0x1ad37f52c 35-[UIPickerTableView layoutSubviews]_block_invoke + 92
13 UIKitCore 0x1ad918a60 +[UIView(Animation) performWithoutAnimation:] + 104
14 UIKitCore 0x1ad37f4c4 -[UIPickerTableView layoutSubviews] + 116
15 UIKitCore 0x1ad925dd4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2500
16 QuartzCore 0x1ade2f280 -[CALayer layoutSublayers] + 296
17 QuartzCore 0x1ade2f73c CA::Layer::layout_if_needed(CA::Transaction*) + 524
18 QuartzCore 0x1ade43b64 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 144
19 QuartzCore 0x1add8b114 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 416
20 QuartzCore 0x1addb6418 CA::Transaction::commit() + 732
21 QuartzCore 0x1addb7778 CA::Transaction::observer_callback(CFRunLoopObserver*, unsigned long, void*) + 96
22 CoreFoundation 0x1aaa5a444 CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 36
23 CoreFoundation 0x1aaa54858 CFRunLoopDoObservers + 576
24 CoreFoundation 0x1aaa54e08 CFRunLoopRun + 1056
25 CoreFoundation 0x1aaa544bc CFRunLoopRunSpecific + 600
26 GraphicsServices 0x1c14d9820 GSEventRunModal + 164
27 UIKitCore 0x1ad3f8734 -[UIApplication _run] + 1072
28 UIKitCore 0x1ad3fde10 UIApplicationMain + 168
29 Applicant.testing 0x104e326a8 main + 20 (AppCoordinator.swift:20)
30 libdyld.dylib 0x1aa71be60 start + 4





My issue
I believe I am having the same issue with a user in 13.7 but I can't reproduce it. Our crash log is almost identical. Does anyone know if this issue has been resolved in newer releases?
This is just an index out of range assert. There are many potential causes of this, so it’s hard to offer concrete advice without seeing a full crash report. For example, luigidm wrote:

Following the stack I can see there is no array involved on my side
and it actually appears to be a consequence of a setter on a
@Published property.

but the backtrace posted by AlexisQapa and the crash report posted by siantz don’t correlate with that. Instead, they show a problem with the integration between SwiftUI and UIPickerView.

So, luigidm, I’m going to repeat my request that you post a full crash report. And AlexisQapa and siantz, I recommend that you start a specific thread about this issue and tag it with SwiftUI.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"

getting this mysterious crash.

This doesn’t seem particularly mysterious. If you access an array out of bounds, Swift will trap with that message. For example, this code:

func main() {
    let a = ["Hello", "Cruel", "World!"]
    print(a[3])
}

main()

crashes with this message:

Swift/ContiguousArrayBuffer.swift:580: Fatal error: Index out of range
2021-09-29 10:41:23.310137+0100 MyTestTool[8120:741471] Swift/ContiguousArrayBuffer.swift:580: Fatal error: Index out of range

If you can reproduce the problem in Xcode, do so, then look at the backtrace in the Debug navigator to see how you got there.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

same error here...it is working with a small array

I'm not mutating the array

TLDR: Surround any Swift UI updates in a:

@State private var myStateVar: [MyState] = []

DispatchQueue.main.async {
    // ... do updates to myStateVar here
}

This was my problem, but Apple didn't help by changing SwiftUI, not telling us about it, not providing a stack trace, and not even providing a code lint in Xcode for state updates. Every other modern framework provides a stack trace back to our own code where we can figure out what we did wrong. It seems only Apple requires you to do some esoteric internal debug dump, send it to Apple, hold your breath, and hope to get a response.

I was updating a SwiftUI Table view, and suddenly, a new version of SwiftUI on macOS (but probably doesn't matter which Apple OS), had this totally unhelpful crash:

ForEach<Binding<Array<Replacement>>, UUID, TableRow<Binding<Replacement>>>: the ID 02A438DA-C928-4FCB-BA5F-518B2C476A6C occurs multiple times within the collection, this will give undefined results! Swift/ContiguousArrayBuffer.swift:675: Fatal error: Index out of range

Totally unhelpful, right? And it's wrong. That ID does NOT appear more than once in the data collection itself. It's the way SwiftUI is handling the updates internally.

My code worked for like 2 years until Apple did an update to SwiftUI that caused this crash.

Here's my code. I am filtering a Table with a search field:

struct ReplacementsView: View {
    var body: some View {
        VStack {
            searchField
            replacementsTable
            actionButtons
        }

    ...

    @State private var searchQuery = ""
    @State private var filteredReplacements: [Replacement] = []

    private func filterReplacements() {
        /// THE PROBLEM IS HERE. Doing a UI @State update synchronously causes a crash here.
        if searchQuery.isEmpty {
            filteredReplacements = replacementsManager.replacements
            return
        }
        filteredReplacements = replacementsManager.replacements.filter { replacement in
            replacement.pattern.lowercased().contains(searchQuery.lowercased()) ||
            replacement.replacement.lowercased().contains(searchQuery.lowercased())
        }
    }

    private var searchField: some View {
        TextField("Search...", text: $searchQuery)
            .textFieldStyle(.roundedBorder)
            .padding([.top, .leading, .trailing])
            .onChange(of: searchQuery) {
                filterReplacements()
            }
    }

    private var replacementsTable: some View {
        ScrollViewReader { proxy in
            Table($filteredReplacements, selection: $selection) {
    ...
                TableColumn("Replacement") { $row in
                    TextField("", text: $row.replacement, onEditingChanged: { editing in
                        if !editing {
                            update(row)
                        }
                    })
                    .accessibilityTextContentType(.sourceCode)
                    .onSubmit {
                        update(row)
                    }
                }
    ...

Now, Poor ChatGPT can't even figure out SwiftUI because the documentation is horrible. The wealthiest company in the world should be able to hire tech writers!!! I wonder if Apple has more than 2 or 3 tech writers to cover all the developer documentation. And even then, 2 or 3 people full time should be able to do better than this.

So finally, after much frustration, it helped me realize I needed to do this async:

private func filterReplacements() {
    DispatchQueue.main.async {
        if searchQuery.isEmpty {
            filteredReplacements = replacementsManager.replacements
            return
        }
        filteredReplacements = replacementsManager.replacements.filter { replacement in
            replacement.pattern.lowercased().contains(searchQuery.lowercased()) ||
            replacement.replacement.lowercased().contains(searchQuery.lowercased())
        }
    }
}

That's it. That's all it was. Surrounded the state update with a DispatchQueue.main.async { ... } and ... voila! No crash.

Now, if this is Apple best practice, why doesn't Apple's new AI in Xcode 16 lint this and yell at me that I should not be updating this synchronously?

Why am I so angry? I am a visually impaired software engineer. It's hard enough for me to read gobs and gobs and gobs of posts and generated non-answers to get to the solution of a very simple problem. And I have to do this a hundred times a day. And this app I wrote is to fix accessibility on my Mac, because Apple's built-in text-to-speech is so very limited. I am angry at Apple because the average user has a hard time finding out how to use their stuff. They go on and on about how great they are on accessibility, yet no, they aren't. Accessibility is Apple's very last concern. Profits before people, always. I've been a Mac user since 2005, and grew up with an Apple //c. Steve Jobs understood people. Apple's current leadership doesn't.

This is why Flutter is a million times better than SwiftUI. Flutter throws an exception and tells you not to update state while the build context is being rendered. Duh. And it runs on everything, not just Apple devices, which makes it that much more valuable. Now, I work in like 3 different languages/frameworks here, not solely on Apple stuff (probably makes me a black sheep here, not to mention being visually impaired and calling out Apple for its lack of true concern about accessibility), and Apple could be doing a lot more to help us, instead of making us spend hours and hours figuring out what Apple could have just told us in the documentation and in its own editor, Xcode, which is solely focused on Apple's ecosystem... and is the least accessible editor on the market, to boot. So why is Xcode so very, very horrible at helping us with this most basic issue?

With the resources available to you, Apple, this treatment of your customers and users is not acceptable.

SwiftUI App crashing on iOS 14 - ContiguousArrayBuffer.swift
 
 
Q