I need to prevent UISwitch
(or Toggle
for SwiftUI) programmatical state change. I just want the state to change with user interaction.
The below code working on debug mode.
SwiftUIView
import SwiftUI
struct SwiftUIView: View {
@State var myState = false
@State var myProvider = MyProvider()
var body: some View {
Toggle("Let me in", isOn: $myState.onChange(myProvider.checkStateAction))
.textFieldStyle(.roundedBorder)
.padding(.trailing).padding(.leading)
}
}
}
@available(iOS 13.0, *)
extension Binding {
func onChange(_ handler: @escaping (Value) -> Void) -> Binding<Value>
{
Binding(
get: { self.wrappedValue },
set: { newValue in
self.wrappedValue = newValue
handler(newValue)
}
)
}
}
MyProvider
import Foundation
public final class MyProvider: NSObject {
public var onCheckBoxStateChanged: ((_ state: Bool) -> Void)?
private(set) var state: Bool = false
internal var stateChanger: Bool = false {
didSet {
state = self.stateChanger
}
}
public override init() {
super.init()
}
@objc public final func checkStateAction(to value: Bool) {
let symbols = Thread.callStackSymbols
let str: String = symbols[3]
if str.contains("sendAction") == false &&
str.contains("SwiftUI7Binding") == false {
print("It's done")
}
state.toggle()
onCheckBoxStateChanged?(state)
}
}
Please tell me how can I do that? Or you can show me another way :)
Thanks..
CodePudding user response:
What you can do is disable the Toggle
's interaction and overlay it with a Button
so that when the user presses on the Toggle
, the button is tapped and you call whatever function you want:
struct SwiftUIView: View {
@State var myState = false
@State var myProvider = MyProvider()
var body: some View {
Toggle("Let me in", isOn: $myState)
.allowsHitTesting(false)
.textFieldStyle(.roundedBorder)
.padding(.trailing).padding(.leading)
.overlay {
Button(action: {
myProvider.checkStateAction()
}) {
Color.clear
}
}
}
}
CodePudding user response:
To disable UISwitch:
switch.isEnabled = false
To put UISwitch off:
switch.isOn = false
To put UISwitch on:
switch.isOn = true
To hide UISwitch:
switch.isHidden = true
CodePudding user response:
struct SwiftUIView: View {
@State var myState = false
var sourceOfTruthValue: Bool {
return sourceOfTruth.wrappedValue
}
private var sourceOfTruth: Binding<Bool> {
var value = false
return Binding {
return value
} set: { newValue in
value = newValue
myState = newValue
}
}
var body: some View {
Toggle("toggle1", isOn: sourceOfTruth)
.textFieldStyle(.roundedBorder)
.padding(.trailing).padding(.leading)
Toggle("toggle2", isOn: $myState)
}
}
Added 2 toggles to experiment with. When toggle1
is changed only then sourceOfTruth
is updated. When toggle2
is updated, sourceOfTruth
is not updated.
Changing myState
won't update the sourceOfTruth
.
You can always read the value of sourceOfTruth
from sourceOfTruthValue
.
You can run the above in a playground:
import PlaygroundSupport
import SwiftUI
struct ContentView: View {
var body: some View {
SwiftUIView()
}
}
PlaygroundPage.current.setLiveView(ContentView())