Reputation: 697
In SwiftUI I'd like to store some key-value pair data in a dictionary. Can I bind an item in the dictionary to TextField or elsewhere that requires Binding?
I want to do something like this:
@State var myDic: [String : String] = [
"name": "Tim"
"company": "Apple"
]
TextField("Name", text: $myDic["name"] ?? "")
where the behavior is:
Upvotes: 1
Views: 62
Reputation: 697
After long-time trying, I have a solution for this problem. I think this can be separated into 2 requirements:
extension Dictionary {
subscript(removeNil key: Key) -> Value? {
get { self[key] }
set {
if let newValue = newValue {
self[key] = newValue
} else {
self.removeValue(forKey: key)
}
}
}
}
public extension Binding where Value: Equatable {
static func ??(binding: Binding<Value?>, fallback: Value) -> Binding<Value> {
Binding(
get: { binding.wrappedValue ?? fallback },
set: {
if binding.wrappedValue == fallback {
binding.wrappedValue = nil
} else {
binding.wrappedValue = $0
}
}
)
}
}
Then it can be used like this:
@State var myDic: [String: String] = [
"a" : "a",
"b" : "b",
]
TextField("foo", text: $myDic[removeNil: "a"] ?? "")
.onChange(of: myDic) {
print(myDic)
}
Testing on macOS 14.4.1: When I type "a", and double "delete" to clear the TextField, the output is like shown below, exactly what is required.
Upvotes: 0
Reputation: 273540
I would create a custom Dictionary
subscript.
extension Dictionary where Value == String {
subscript(emptyStringAsNil key: Key) -> Value {
get { self[key] ?? "" }
set { self[key] = newValue.isEmpty ? nil : newValue }
}
}
Usage:
TextField("Foo", text: $myDic[emptyStringAsNil: "name"])
Upvotes: 3