Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my SwiftUI @State variable null the fist time my sheet appears?

Tags:

null

swiftui

In the view shown below there is a simple list of 3 items. When the user selects an item in the list a sheet is presented showing the name of the item selected. However, when I run it, the first time I select an item it shows "item was null". If I select another item in the list it works perfectly. If I go back and select the first item again, it now works.

Can someone tell me why the selectedItem variable is null the first time a button is clicked?

struct TestView: View {
    @State private var showSheet = false
    @State private var selectedItem: String?
    
    var body: some View {
        List {
            Button(action: {
                selectedItem = "Item 1"
                showSheet = true
            }, label: { Text("Item 1") })
            Button(action: {
                selectedItem = "Item 2"
                showSheet = true
            }, label: { Text("Item 2") })
            Button(action: {
                selectedItem = "Item 3"
                showSheet = true
            }, label: { Text("Item 3") })
        }
        .sheet(isPresented: $showSheet) {
            Text(selectedItem ?? "item was null")
        }
        
    }
}
like image 888
Falco Avatar asked Sep 05 '25 03:09

Falco


1 Answers

As discussed in the comments, you're going to need to use .sheet(item:). The reason for this is that the common .sheet(isPresented:) is created before the button is tapped.

When using .sheet(item:) the string needs to be identifiable, but you can achieve that with a simple extension. And now you also don't need the showSheet bool, because the sheet is now bound to selectedItem. Keep in mind that this means that selectedItem is set to nil when the sheet is dismissed.

An example of what this solution could look like for your code is as follows:

struct TestView: View {

    @State private var selectedItem: String?
    
        var body: some View {
            List {
                Button(action: {
                    selectedItem = "Item 1"
                }, label: { Text("Item 1") })
                Button(action: {
                    selectedItem = "Item 2"
                }, label: { Text("Item 2") })
                Button(action: {
                    selectedItem = "Item 3"
                }, label: { Text("Item 3") })
            }
            .sheet(item: $selectedItem, content: { item in
                Text(item)
            })
            }
            
        }

extension String: Identifiable {
    public var id: String { return self }
}
like image 145
Prolix Avatar answered Sep 07 '25 21:09

Prolix