iOS: List selection is reset to nil when app is sent to background

For some reason, a List will reset its selection to nil when the app is in the background.

Steps to reproduce the issue:

  • Run attached sample project
  • Once the app has launched, select a name in the sidebar
  • Move the app to the background
  • Wait a few seconds
  • Bring back the app to the foreground

Expected result:

The list selection should still be valid

Actual result:

The list selection is set to nil

Notes:

I’m using a StateObject, which should be the way to ensure that data isn’t regenerated when views are rendered. Is this a bug or something else needs to be taken care of?

class AppModel: ObservableObject {
    @Published var selectedPerson: Person?
}


@main

struct NilListSelectionApp: App {
    @StateObject var appModel = AppModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appModel)
        }
    }
}
struct Person: Identifiable, Hashable {
    let id: UUID
    let firstname: String

    init(firstname: String) {
        id = UUID()
        self.firstname = firstname
    }
}


struct ContentView: View {
    @EnvironmentObject private var appModel: AppModel

    var body: some View {
        NavigationSplitView {
            SidebarView()
        } detail: {
            PersonView(person: appModel.selectedPerson)
        }
    }
}


struct SidebarView: View {
    @EnvironmentObject private var appModel: AppModel

    private let persons = [Person(firstname: "Joe"), Person(firstname: "Jane")]

    var body: some View {
        List(persons, id:\.self, selection: $appModel.selectedPerson) { person in
            Text(person.firstname).tag(person)
        }
        .listStyle(.sidebar)
    }
}


struct PersonView: View {
    let person: Person?

    var body: some View {
        if let person {
            Text(person.firstname)
        }
        else {
            Text("No Selection")
        }
    }
}

Apple folks: FB11876396

The first thing to check is whether your app is getting terminated while it's in the background (which is quite possible, since it's not doing anything then). If so, then it's going to be relaunched when it comes back to the foreground, and you'll need to use some kind of state restoration to put the UI back into the state it was:

https://developer.apple.com/documentation/uikit/view_controllers/preserving_your_app_s_ui_across_launches https://developer.apple.com/documentation/uikit/uiscenedelegate/restoring_your_app_s_state

I got the same problem. My situation is the code works fine on Mac and iPhone, no setting to nil on the background, but the problem occurs occasionally on the iPad (not every time, 1/3 I guess).

I "fix" this by the save the selection to a temp variable onChange of the @Environment(.scenePhase)

.onChange(of: scenePhase) { phase in
            if phase == .background{
                tempSelectedId = selectedId
            } else {
                if phase == .inactive && selectedId == nil{
                    selectedId = tempSelectedId
                    print("Restore - scenePhase")
                }
            }
        }

Having the same issue as described above.

Just wanted to add, I also have the same issue described above.

Same issue for me.

Strangely, this problem does not happen when "Requires full screen" is enabled.

But we want to avoid this approach...

This code works for me

.onChange(of: sideBarSelection) { [sideBarSelection] newValue in
            if newValue == nil {
                self.sideBarSelection = sideBarSelection
            }
        }

The newest iOS17 beta fixes this bug.

iOS: List selection is reset to nil when app is sent to background
 
 
Q