Reputation: 75
I have a class which I want to initialize with a Binding var that is set in another View.
The View:
struct CoverPageView: View {
@State var numberOfNumbers: Int
var body: some View {
NavigationView {
GeometryReader { geometry in
VStack(alignment: .center, spacing: 0){
TextField("Multiplication Up to:", value: self.$numberOfNumbers, formatter: NumberFormatter())
}
}
}
}
The class which needs to be initialized using the @Binding var $numberOfNumbers:
import SwiftUI
class MultiplicationPractice: ObservableObject {
@Binding var numberOfNumbers: Int
var classNumOfNumbers: Int
init() {
self.classNumOfNumbers = self.$numberOfNumbers
}
}
The init statement obviously gives the error that self is not initialized and the instance var is being used to initialize, which is not allowed.
How do I circumvent this? The class needs to be initialized with the number the user enters in the first view. I have written approx. code here so ignore any typos please.
Upvotes: 6
Views: 12232
Reputation: 813
Typically you'd initialize MultiplicationPractice in CoverPageView with a starting value:
@ObservedObject var someVar = MultiplicationPractice(NoN:123)
And of course, add a supporting init statement:
class MultiplicationPractice:ObservableObject {
init(NoN: Int) {
self.numberOfNumbers = val
}
and you wouldn't want to wrap your var with @Binding, instead wrap it with @Published:
class MultiplicationPractice:ObservableObject {
@Published var numberOfNumbers:Int
...
In your particular case I would even drop the numberOfNumbers
var in your CoverPageView
, and instead use the direct variable of the above someVar
:
struct CoverPageView: View {
//removed @State var numberOfNumbers:Int
@ObservedObject var someVar = MultiplicationPractice(123)
...
TextField("Multiplication Upto:", value: self.$someVar.numberOfNumbers, formatter: NumberFormatter())
You'll notice that I passed in the sub-var of the @ObservedObject as a binding. We can do this with ObservableObjects.
I see now what you're trying to do, you want to pass a binding along across your ViewModel, and establish an indirect connection between your view and model. While this may not be the way I'd personally do it, I can still provide a working example.
Here is a simple example using your struct names:
struct MultiplicationGame {
@Binding var maxNumber:String
init(maxNumber: Binding<String>) {
self._maxNumber = maxNumber
print(self.maxNumber)
}
}
class MultiplicationPractice:ObservableObject {
var numberOfNumbers: Binding<String>
@Published var MulGame:MultiplicationGame
init(numberOfNumbers: Binding<String> ) {
self.numberOfNumbers = numberOfNumbers
self.MulGame = MultiplicationGame(maxNumber: numberOfNumbers)
}
}
struct ContentView: View {
@State var someText: String
@ObservedObject var mulPractice: MultiplicationPractice
init() {
let state = State(initialValue: "")
self._someText = state
self.mulPractice = MultiplicationPractice(numberOfNumbers: state.projectedValue)
}
var body: some View {
TextField("put your text here", text: $someText)
}
}
Upvotes: 3
Reputation: 2446
Okay, I don't really understand your question so I'm just going to list a few examples and hopefully one of them will be what you're looking for.
struct SuperView: some View {
@State var value: Int = 0
var body: some View {
SubView(value: self.$value)
}
}
struct SubView: View {
@Binding var value: Int
// This is the same as the compiler-generated memberwise initializer
init(value: Binding<Int>) {
self._value = value
}
var body: some View {
Text("\(value)")
}
}
If I misunderstood and you're just trying to get the current value, do this
struct SuperView: some View {
@State var value: Int = 0
var body: some View {
SubView(value: self.value)
}
}
struct SubView: View {
let value: Int
// This is the same as the compiler-generated memberwise initializer
init(value: Int) {
self.value = value
}
var body: some View {
Text("\(value)")
}
}
Upvotes: 0