Reputation: 878
I’m having an issue with SwiftUI with optional bindings, basically it’s a List on macOS, where I add a DetailView once an item is selected, if not selected just add a Text.
When I open the app it’s fine, the Text appears, then I add some items and select it, also works fine, DetailView appears, but once I click outside the table, unselecting it, it crashes. Even tough I have a conditional checking for nil, that’s why it works the first time.
I guess the DetailView is keeping a reference to the selectedItem and crashing once it’s set to nil, but I thought the entire body should be refreshed once a State property is changed, which would remove the previous DetailView from memory and not call a new one, right?
Here's the code:
import SwiftUI
struct DetailView: View {
@Binding var text: String
var body: some View {
TextField("123", text: self.$text)
}
}
struct ContentView: View {
@State var text = ""
@State var items = [String]()
@State var selectedItem: String? = nil
var body: some View {
VStack {
HStack {
VStack(alignment: .leading, spacing: 0) {
List(selection: $selectedItem) {
ForEach(items, id: \.self) { item in
Text(item)
}
}
HStack(spacing: 0) {
Button(action: {
self.items.append(UUID().uuidString)
}, label: {
Text("Add")
})
Button(action: {
if let item = self.selectedItem {
self.items.remove(at: self.items.firstIndex(of: item)!)
}
self.selectedItem = nil
}, label: {
Text("Remove")
}).disabled(selectedItem == nil)
}
}
if selectedItem != nil {
DetailView(text: Binding($selectedItem)!)
} else {
Text("Add an item")
}
}
.tabItem {
Text("Test")
}
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
Upvotes: 1
Views: 429
Reputation: 257889
I guess the DetailView is keeping a reference to the selectedItem and crashing once it’s set to nil, but I thought the entire body should be refreshed once a State property is changed, which would remove the previous DetailView from memory and not call a new one, right?
The order of update is not defined, so I would answer no on above.
Here is a solution. Tested with Xcode 11.4 / iOS 13.4
if selectedItem != nil {
DetailView(text: Binding(get: {self.selectedItem ?? ""},
set: {self.selectedItem = $0}))
} else {
Text("Add an item")
}
Upvotes: 1