【问题标题】:Do something when Toggle state changes当切换状态改变时做一些事情
【发布时间】:2020-12-29 23:58:44
【问题描述】:

我正在使用 SwiftUI,并且想在切换状态更改时做一些事情,但我找不到解决方案。

当切换状态发生变化时,我如何调用函数或执行任何操作?

@State var condition = false

Toggle(isOn: $condition) {
    Text("Toggle text here")
}

【问题讨论】:

  • 通常您不会需要因为事件而调用函数。将您的视图视为状态的函数。当condition 更改时,body 将被重新评估并反映该值。您可以通过在您的Text 视图中包含(可打印形式的)condition 轻松观察到这一点...
  • @Alladinian 如果您想通过翻转开关触发一些额外的逻辑,但不改变视图层次结构中的任何内容,该怎么办?开关不仅可以控制其他视图的外观,还可以控制。表示我们可能想要保存然后在应用的其他部分读取的一些用户偏好。
  • @raven_raven 我的第一个想法是,它可能是ObservableObject@Published 属性,而不是@State。然后,您可以使用任何 Combine 运算符来做任何您想做的事情,作为对值变化的反应。

标签: ios swift xcode swiftui


【解决方案1】:

如果你想在切换状态改变时做一些事情,你可以使用 didSet。

struct ContentView: View {

    @State var condition = false{
        didSet{
            print("condition changed to \(condition)")
        }
    }

    var body: some View {

       let bind = Binding<Bool>(
          get:{self.condition},
          set:{self.condition = $0}
        )

        return Toggle(isOn: bind){
            Text("Toggle text here")
        }
    }
}

当我们说@State var condition = true 时,它的类型是State&lt;Bool&gt; 而不是Bool。 当我们在切换中使用绑定时(在这种情况下为$condition),切换直接更改存储的值。这意味着它永远不会改变@State,所以 didSet 永远不会被触发。

所以在这里我们创建并分配给let bind 一个Binding&lt;Value&gt; 结构的实例,并在toggle 中直接使用该Binding 结构。比我们设置self.condition = $0时,会触发didSet。

【讨论】:

  • 我们不需要声明绑定值。 $condition 完成这项工作
【解决方案2】:

您可以像下面的第一个示例一样使用.onChange 修饰符。

但是,请记住,在大多数情况下我们不需要它。

  • 在视图设置的情况下,您绑定到 @State 布尔值,然后使用该布尔值修改视图层次结构,如第一个示例所示。

  • 如果您的模型发生更改,您可以将切换绑定到模型或模型控制器中的 @Published 值。在这种情况下,模型或模型控制器从开关接收更改,执行任何请求,然后重新呈现视图。它必须有一个对您的模型的 @ObservedObject 引用。

我在第一个示例中展示了如何使用.onChange 修饰符。它只是记录状态。

请记住,SwiftUI 视图中的逻辑应该尽可能少。 顺便说一句,这在 SwiftUI 发明之前就已经是真的了;)

示例 1 - @State 值。 (本地用户界面设置)

import SwiftUI

struct ToggleDetailView: View {
    @State var isDetailVisible: Bool = true

    var body: some View {
        VStack {
            Toggle("Display Detail", isOn: $isDetailVisible)
                .onChange(of: self.isDetailVisible, perform: { value in
                    print("Value has changed : \(value)")
                })
            if isDetailVisible {
                Text("Detail is visible!")
            }
        }
        .padding(10)
        .frame(width: 300, height: 150, alignment: .top)
    }
}

struct ToggleDetailView_Previews: PreviewProvider {
    static var previews: some View {
        ToggleDetailView()
    }
}

示例 2 - @ObservedObject 值。 (对模型的操作)

import SwiftUI

class MyModel: ObservableObject {
    @Published var isSolid: Bool = false
    
    var string: String {
        isSolid ? "This is solid" : "This is fragile"
    }
}

struct ToggleModelView: View {
    @ObservedObject var model: MyModel
    
    var body: some View {
        VStack {
            Toggle("Solid Model", isOn: $model.isSolid)
            Text(model.string)
        }
        .padding(10)
        .frame(width: 300, height: 150, alignment: .top)
    }
}

struct ToggleModelView_Previews: PreviewProvider {
    static var previews: some View {
        ToggleModelView(model: MyModel())
    }
}

【讨论】:

    【解决方案3】:

    试试

    struct ContentView: View {
    
        @State var condition = false
    
    
        var body: some View {
    
            if condition {
    
               callMe()
            }
            else {
    
                print("off")
            }
              return Toggle(isOn: $condition) {
                  Text("Toggle text here")
              }
    
        }
    
        func callMe() {
    
    
        }
    }
    

    【讨论】:

    • 1.嗨@Sh_Khan,SwiftUI 不止一次调用 body,您的解决方案可能会起作用,但如果 callMe 函数进行大量计算或发出网络请求,那是一种黑客行为。 2.关于你的答案的问题 SwiftUI 是否在每次更改切换状态时调用 body 属性?
    • 每次状态变化只调用一次
    【解决方案4】:

    卡伦请检查

    @State var isChecked: Bool = true
    @State var index: Int = 0
    Toggle(isOn: self.$isChecked) {
        Text("This is a Switch")
        if (self.isChecked) {
            Text("\(self.toggleAction(state: "Checked", index: index))")
        } else {
            CustomAlertView()
            Text("\(self.toggleAction(state: "Unchecked", index: index))")
        }
    }
    

    添加这样的功能

    func toggleAction(state: String, index: Int) -> String {
    print("The switch no. \(index) is \(state)")
    return ""
    }
    

    【讨论】:

    • 感谢您的回答,但这不起作用。更改切换状态后,SwiftUI 不会调用标签块
    【解决方案5】:

    我倾向于使用:

    Toggle(isOn: $condition, label: {
                    Text("Power: \(condition ? "On" : "Off")")
                })
        .padding(.horizontal, 10.0)
        .frame(width: 225, height: 50, alignment: .center)
    

    【讨论】:

      猜你喜欢
      • 2013-09-04
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多