Cómo cambiar el estado de un Toggle de SwiftUI externamente
Estoy intentando cambiar el estado de un Toggle desde fuera de la vista. He intentado utilizar ObservableObject y EnvironmentObject, pero el toggle espera un Binding (@State).
- Necesito ejecutar una devolución de llamada cuando el usuario toque el toggle.
- Necesito cambiar el estado del toggle programáticamente sin ejecutar la devolución de llamada.
- Estoy usando un modelo compartido para esto y otras vistas, idealmente me gustaría poder usar eso para un Bool ‘enabled’ en lugar de la variable de estado isOn.
Este código me permite ejecutar la devolución de llamada a través de la extensión, pero no puedo averiguar cómo cambiar la variable de estado isOn externamente, y si pudiera hacerlo, supongo que mi devolución de llamada se ejecutaría, lo cual no quiero que suceda.
import SwiftUI
struct ControlView: View {
var title: String
var panel: Int
var callback: () -> Void
@State public var isOn = false // toggle state
@EnvironmentObject var state: MainViewModel
var body: some View {
VStack() {
// -- Header
HStack() {
Text(" ")
Image(self.state.panelIcon(panel: panel)).resizable().frame(width: 13.0, height: 13.0)
Text(title)
Spacer()
}.padding(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0))
.background(Color(red: 0.9, green: 0.9, blue: 0.9))
// -- Switch
Toggle(isOn: $isOn.didSet { (state) in
// Activar ARC
callback()
}) {
Text("Habilitar ARC")
}.padding(EdgeInsets(top: 0, leading: 12, bottom: 10, trailing: 12))
}.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color(red: 0.8, green: 0.8, blue: 0.8), lineWidth: 1.25)
).background(Color.white)
}
}
extension Binding {
func didSet(execute: @escaping (Value) -> Void) -> Binding {
return Binding(
get: { self.wrappedValue },
set: {
self.wrappedValue = $0
execute($0)
}
)
}
}
(Note: The code and output provided are not in markdown format)
davy.ai
Para cambiar el estado de un Toggle desde fuera de la vista, puedes usar una Binding en lugar de una variable @State. Para ejecutar una devolución de llamada cuando el usuario toca el Toggle, puedes utilizar el modificador didSet en el Binding. Sin embargo, esto también ejecutaría la devolución de llamada cuando la variable de estado cambie programáticamente.
Para evitar que la devolución de llamada se ejecute cuando el estado cambia programáticamente, puedes usar una variable flag para indicar si el cambio de estado fue iniciado por el usuario o por el código.
Para utilizar un modelo compartido para un Bool ‘enabled’ en lugar de la variable @State isOn, puedes pasar la variable enabled como parámetro a ControlView y usarla para el Binding.
Aquí tienes un ejemplo de fragmento de código con estos cambios:
Para utilizar esta vista, puedes pasar la bandera enabled como un Binding a ControlView:
Y puedes cambiar el estado del toggle programáticamente cambiando el valor de la variable enabled: