gurehbgui
gurehbgui

Reputation: 14684

Why my SwiftUI List is not getting updated?

I use a SwiftUI List and pass a String to a different view via a Binding. But the list get not updated when I went back.

Here is my example:

struct ContentView: View {
    @State private var list = ["a", "b", "c"]
    @State private var item: String?
    @State private var showSheet = false
    
    
    var body: some View {
        List {
            ForEach(list.indices) { i in
                Button(action: {
                    item = list[i]
                    showSheet.toggle()
                }) {
                    Text(list[i])
                }
                
                
            }
        }
        .sheet(isPresented: $showSheet, content: {
            DetailView(input: $item)
        })
    }
}

And the detail page:

struct DetailView: View {
    @Binding var input: String?
    
    var body: some View {
        Text(input ?? "")
        .onDisappear{
            print("changed to changed")
            input = "changed"
        }
    }
}

What I want to achieve is, that on every Item I click, I see the detail page. After that the element should change to "changed". But this does not happen. Why?

Upvotes: 2

Views: 141

Answers (2)

pawello2222
pawello2222

Reputation: 54436

I recommend you use .sheet(item:content:) instead of .sheet(isPresented:content:)

struct ContentView: View {
    @State private var items = ["a", "b", "c"]
    @State private var selectedIndex: Int?

    var body: some View {
        List {
            ForEach(items.indices) { index in
                Button(action: {
                    selectedIndex = index
                }) {
                    Text(items[index])
                }
            }
        }
        .sheet(item: $selectedIndex) { index in
            DetailView(item: $items[index])
        }
    }
}

struct DetailView: View {
    @Binding var item: String

    var body: some View {
        Text(item)
            .onDisappear {
                print("changed to changed")
                item = "changed"
            }
    }
}

This will, however, require the selectedIndex to conform to Identifiable.

You can either create an Int extension:

extension Int: Identifiable {
    public var id: Int { self }
}

or create a custom struct for your data (and conform to Identifiable).

Upvotes: 1

Asperi
Asperi

Reputation: 257563

You update item but not list, so don't see any result. Here is corrected variant - store selected index and pass binding to list by index.

Tested with Xcode 12.1 / iOS 14.1

struct ContentView: View {
    @State private var list = ["a", "b", "c"]
    @State private var item: Int?
    
    
    var body: some View {
        List {
            ForEach(list.indices) { i in
                Button(action: {
                    item = i
                }) {
                    Text(list[i])
                }
            }
        }
        .sheet(item: $item, content: { i in
                DetailView(input: $list[i])
        })
    }
}

extension Int: Identifiable {
    public var id: Self { self }
}

struct DetailView: View {
    @Binding var input: String
    
    var body: some View {
        Text(input)
        .onDisappear{
            print("changed to changed")
            input = "changed"
        }
    }
}

Upvotes: 1

Related Questions