skip to Main Content

I have a state variable of a struct with 2 numbers. I have a selection box for the 1st one, and a selection box for the 2nd one which should cap it at the 1st one. I implemented the capping logic with didSet. The value of the selections did change, but not the text that display the selected value for the 2nd one. Here’s the pseudo code. Any idea?

struct CustomTaskView: View {
  @State private var options: MyClass {
    didSet {
      if options.a > options.b {
        options.a = options.b
      }
    }
  }

  var body: some View {
    // selection box for options.a
    // selection box for options.b
    // ...
    Text("(options.a)")
    Text("(options.b)")
  }
}

2

Answers


  1. You may have made it with spit and duct tape, but this is not how you should do it in the first place!

    First of all, you need to separate the View logic from the Model logic. Then you can decide where to put the required behavior. For example, you can do it in the View like this:

    struct CustomTaskView: View {
        @State private var options: MyClass
    
        var firstTitle: String { "(min(options.a, option.b))" }
        var secondTitle: String { "(options.b)" }
    
        var body: some View {
            Text(firstTitle)
            Text(secondTitle)
        }
    }
    

    Or move it to the model. Something like:

    @Observable
    class MyClass {
        var a: Int = 0
        var b: Int = 5
    
        func action() {
            a += 1
            if a > b { a = b }
        }
    }
    
    struct CustomTaskView: View {
        let options = MyClass()
    
        var body: some View {
            Button("Action") { options.action() }
    
            Text("(options.a)")
            Text("(options.b)")
        }
    }
    

    Note that these are simple demonstrations and you should check all logic based on your actually needs

    Login or Signup to reply.
  2. You declare @State private var options: MyClass ..., then
    you also need to instantiate it, as shown in the example code.

    Note, your code is not how SwiftUI should be used.

    struct MyClass {
        var a: Int
        var b: Int
    }
    
    struct CustomTaskView: View {
        
        @State private var options: MyClass {
            didSet {
                if options.a > options.b {
                    options.a = options.b
                }
            }
        }
        
        init() {
            _options = State(initialValue: MyClass(a: 1, b: 2))  // <-- here
        }
        
        var body: some View {
            VStack {
                Button("click me") {
                    options = MyClass(a: 5, b: 4) // <-- for testing
                }
                Text("(options.a)")
                Text("(options.b)")
            }
        }
    }
    
    struct ContentView: View {
        var body: some View {
            CustomTaskView()
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search