SwiftUI: get rid of SelectionManagerBox<String> tried to update multiple times per frame
Asked Answered
B

2

11

I spent a few hours trying to get rid if this error message on my app:

List with selection: SelectionManagerBox<String> tried to update multiple times per frame.

It is a macOS 14 app. As I wasn't able to find a fix, I decided to try to create a minimal reproductible example. And here is this example:

import SwiftUI

struct ContentView: View {
    @State var selection: String = ""
    @State var secondSelection: String = ""
    
    var body: some View {
        NavigationSplitView {
            List(selection: $selection) {
                NavigationLink("A", value: "A")
                NavigationLink("B", value: "B")
                NavigationLink("C", value: "C")
            }
        } content: {
            List(selection: $secondSelection) {
                NavigationLink("1", value: "1")
                NavigationLink("2", value: "2")
                NavigationLink("3", value: "3")
            }
        } detail: {
            Text("\(selection) - \(secondSelection)")
        }
    }
}

#Preview {
    ContentView()
}

As this example is really really simple, I suppose we can't do anything? Thanks!

I tried everything on my app but the issue seems to be linked to SwiftUI and NavigationSplitView…

Barnet answered 3/10, 2023 at 19:59 Comment(4)
Probably a bug, I would report to Apple. It likely has to do with the whole “column” setup and having 2 selections that push to the navigation.Keitt
@loremipsum Okay so I suppose I just have to ignore this strange message. Thanks! I’ve reported it to Apple.Barnet
Just a guess, the sample seems simple enough it shouldn’t be an issue. Have you tried w/o the selection?Keitt
The sample doesn’t correspond to my app but is a minimal reproductible example. But yes, without selection, no message.Barnet
T
0

I got the same message when I had a onAppear to auto-select the first navigation item. I'm also using an optional for the selected nav item.

Adding a very short sleep got rid of the message (workaround for now):

enum NavItem: String, Hashable {
    case home
    case buy
}

struct MyView: View {
    @State private var selectedNavItem: NavItem?

    var body: some View {
        NavigationSplitView() {
            List(selection: $selectedNavItem) {
                NavigationLink(value: NavItem.home) { homeLabel }
                NavigationLink(value: NavItem.buy) { buyLabel }
            }
        } detail: {
            switch selectedNavItem {
                case .some(.home):
                    HomeView()
                case .some(.buy):
                    BuyView()
                case .none:
                    Text("")
            }
        }
        .onAppear {
            Task { @MainActor in
                try await Task.sleep(for: .seconds(0.05))
                selectedNavItem = .home
            }
        }
    }

    private var homeLabel: some View { ... }
    private var buyLabel: some View { ... }
}
Tightrope answered 19/2, 2024 at 15:56 Comment(0)
B
0

I fixed this by just using a Label instead of a NavigationLink.


import SwiftUI

enum SidebarItem: CaseIterable, Identifiable {
    case item1
    
    var id: Self { self }
    
    @ViewBuilder
    var sidebarLabel: some View {
        switch self {
        case .item1:
            Label("Item 1", systemImage: "bolt.fill")
        }
    }
    
    @ViewBuilder
    var detailView: some View {
        switch self {
        case .item1:
            Text("Item 1 Selected")
        }
    }
}

public struct SidebarView: View {
    @State private var selectedSidebarItem: SidebarItem?
    
    public init() {
    }
    
    public var body: some View {
        NavigationSplitView {
            List(SidebarItem.allCases, selection: $selectedSidebarItem) { item in
                item.sidebarLabel
            }
        } detail: {
            if let selectedSidebarItem {
                selectedSidebarItem.detailView
            } else {
                Text("Select Something")
            }
        }
    }
}

#Preview {
    SidebarView()
}
Barrybarrymore answered 18/8, 2024 at 11:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.