Reputation: 53
I've been trying to create a small calendar app with SwiftUI and ran into some issues while trying to pass a value to a child view and use it in its init.
My code looks like this:
ContentView (parent view):
struct ContentView: View {
@State var selectedMonth: Date
var body: some View {
MonthGridView(selectedMonth: $selectedMonth)
}
}
MonthGridView (child view):
struct MonthGridView: View {
@Binding private var selectedMonth: Date
var days: [Int]
//this is the part where I'm having troubles
init(selectedMonth: Binding<Date>) {
self._selectedMonth = selectedMonth
days = dayIndices(currentMonth: $selectedMonth) //custom function, also in this line is the error right now
}
var body: some View {
//code
}
}
I have looked through a lot of posts on here and a wide variety of tutorials and this is what I came up with. I've tried moving some code around, but wasn't able to get it fully working. I imagine the problem is somewhere around the init, maybe about the Binding wrapper, but I was unable to find information about how to unwrap it.
Appreciate any help getting this working.
Upvotes: 0
Views: 1252
Reputation: 385998
It'll be easier to understand the problem if we “de-sugar” the @Binding
property wrapper. When you say this:
@Binding private var selectedMonth: Date
Swift translates that into this:
private var _selectedMonth: Binding<Date>
private var $selectedMonth: Date { _selectedMonth.projectedValue }
private var selectedDate: Date {
get { _selectedMonth.wrappedValue }
nonmutating set { _selectedMonth.wrappedValue }
}
Here is your init
again:
init(selectedMonth: Binding<Date>) {
self._selectedMonth = selectedMonth
days = dayIndices(currentMonth: $selectedMonth) //custom function, also in this line is the error right now
}
You're using $selectedMonth
before days
has been initialized. But as I showed above, $selectedMonth
is a computed property. You are not allowed to call any methods on self
before self
is fully initialized, and the getter of a computed property counts as a method.
In general, you can work around the limitation by accessing _selectedMonth.projectedValue
directly:
days = dayIndices(currentMonth: _selectedMonth.projectedValue)
However, in this case, all of _selectedMonth
, _selectedMonth.projectedValue
, and the init
parameter selectedMonth
are the same Binding
, you can use any of them directly. So either of these will also work:
days = dayIndices(currentMonth: selectedMonth)
days = dayIndices(currentMonth: _selectedMonth)
Upvotes: 2