I have a SwiftData object called Asset
. Asset
has an optional relationship to another SwiftData object called Income
. Income has an Int?
called cashflow
.
AssetsListView
shows a list of assets and has a + button to create an asset object and show the AddEditAssetView
where the user can fill in the values on the asset.
The newly added asset is a @State
variable in AssetsListView
.
That asset is a @Binding
in AddEditAssetView
.
In AddEditAssetView
, I use a custom view called MoneyTextField
which is just a simple wrapper around a standard TextField
but it does some customized formatting and such.
One of these MoneyTextField
s that I'm showing is so the user can edit the cashflow
amount which is found in $asset.income.cashflow
.
MoneyTextField("placeholder text", value: $asset.income.cashflow)
// inside MoneyTextField, value is: @Binding var value: Int?
But since all relationships in SwiftData need to be optional, $asset.income
is a Income?
and so I get the understandable error:
Value of optional type 'Income?' must be unwrapped to refer to member 'cashflow' of wrapped base type 'Income'
But if I change it to:
MoneyTextField("placeholder text", value: $asset.income?.cashflow)
I get the error:
Cannot use optional chaining on non-optional value of type 'Binding<Income?>'
When $asset
is my @Binding
, how do I pass $mybinding.property.otherproperty
as a binding to a subview?
I'm a long time ObjC app dev, new-ish to swift and brand new to swiftui, so I'm kind of lost. Is there a simple way to do what I'm doing or is my entire approach wrong because I'm not thinking in a proper swiftui mind yet?
More code for context:
struct AssetsView: View {
@State var addedasset: Asset?
// more stuff
var body: some View {
NavigationStack {
List {
MoreStuff()
}
.toolbar {
ToolbarItem {
Button {
let asset = Asset(name: "", assetType: .realestate)
self.addedasset = asset
self.modelContext.insert(asset)
} label: {
Image(systemName: "plus")
}
.fullScreenCover(isPresented: $showingaddscreen) {
AddEditAssetView(player: $player, asset: $addedasset)
}
}
}
}
}
}
struct AddEditAssetView: View {
@Binding var asset: Asset
var body: some View {
NavigationStack {
Form {
OtherStuff()
// here's where the compile error is
MoneyTextField(localizedstringkey: "realestate_cashflow_eg", value: $asset.income?.cashflow)
}
}
}
}
struct MoneyTextField: View {
var localizedstringkey: LocalizedStringKey
@Binding var value: Int?
@State var valuestring = ""
var body: some View {
TextField(localizedstringkey, text: $valuestring)
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
.onReceive(Just(valuestring), perform: { foo in
print("onReceive: foo | \(String(describing: foo))")
updatevalueint(valstring: foo)
})
.onAppear {
if let intval = self.value {
updatevaluestring(val: intval)
}
}
}
}