Bre*_*ger 39 toggle swift swiftui
在我的 SwiftUI 视图中,当 Toggle() 更改其状态时,我必须触发一个操作。切换本身只需要一个绑定。因此,我尝试在 @State 变量的 didSet 中触发操作。但是 didSet 永远不会被调用。
是否有任何(其他)方式来触发一个动作?或者有什么方法可以观察@State 变量的值变化?
我的代码如下所示:
struct PWSDetailView : View {
@ObjectBinding var station: PWS
@State var isDisplayed: Bool = false {
didSet {
if isDisplayed != station.isDisplayed {
PWSStore.shared.toggleIsDisplayed(station)
}
}
}
var body: some View {
VStack {
ZStack(alignment: .leading) {
Rectangle()
.frame(width: UIScreen.main.bounds.width, height: 50)
.foregroundColor(Color.lokalZeroBlue)
Text(station.displayName)
.font(.title)
.foregroundColor(Color.white)
.padding(.leading)
}
MapView(latitude: station.latitude, longitude: station.longitude, span: 0.05)
.frame(height: UIScreen.main.bounds.height / 3)
.padding(.top, -8)
Form {
Toggle(isOn: $isDisplayed)
{ Text("Wetterstation anzeigen") }
}
Spacer()
}.colorScheme(.dark)
}
}
Run Code Online (Sandbox Code Playgroud)
所需的行为是当 Toggle() 更改其状态时触发操作“PWSStore.shared.toggleIsDisplayed(station)”。
paw*_*222 57
如果您使用的是SwiftUI 2 / iOS 14,您可以使用onChange:
struct ContentView: View {
@State private var isDisplayed = false
var body: some View {
Toggle("", isOn: $isDisplayed)
.onChange(of: isDisplayed) { value in
// action...
print(value)
}
}
}
Run Code Online (Sandbox Code Playgroud)
The*_*d27 37
这是一个不使用 tapGesture 的版本。
@State private var isDisplayed = false
Toggle("", isOn: $isDisplayed)
.onReceive([self.isDisplayed].publisher.first()) { (value) in
print("New value is: \(value)")
}
Run Code Online (Sandbox Code Playgroud)
Ene*_*man 27
这是一种更通用的方法,您可以将其Binding应用于几乎所有内置的Views,如 Pickers、Textfields、Toggle..
extension Binding {
func didSet(execute: @escaping (Value) -> Void) -> Binding {
return Binding(
get: { self.wrappedValue },
set: {
self.wrappedValue = $0
execute($0)
}
)
}
}
Run Code Online (Sandbox Code Playgroud)
用法很简单;
@State var isOn: Bool = false
Toggle("Title", isOn: $isOn.didSet { (state) in
print(state)
})
Run Code Online (Sandbox Code Playgroud)
@State private var isOn = false
var body: some View {
Toggle("Title", isOn: $isOn)
.onChange(of: isOn) { _isOn in
/// use _isOn here..
}
}
Run Code Online (Sandbox Code Playgroud)
小智 14
我认为最干净的方法是使用自定义绑定。有了这个,您可以完全控制切换何时实际切换
import SwiftUI
struct ToggleDemo: View {
@State private var isToggled = false
var body: some View {
let binding = Binding(
get: { self.isToggled },
set: {
potentialAsyncFunction($0)
}
)
func potentialAsyncFunction(_ newState: Bool) {
//something async
self.isToggled = newState
}
return Toggle("My state", isOn: binding)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 11
我觉得没问题
struct ToggleModel {
var isWifiOpen: Bool = true {
willSet {
print("wifi status will change")
}
}
}
struct ToggleDemo: View {
@State var model = ToggleModel()
var body: some View {
Toggle(isOn: $model.isWifiOpen) {
HStack {
Image(systemName: "wifi")
Text("wifi")
}
}.accentColor(.pink)
.padding()
}
}
Run Code Online (Sandbox Code Playgroud)
我找到了一个更简单的解决方案,只需使用 onTapGesture:D
Toggle(isOn: $stateChange) {
Text("...")
}
.onTapGesture {
// Any actions here.
}
Run Code Online (Sandbox Code Playgroud)
.init是Binding的构造函数
@State var isDisplayed: Bool
Toggle("some text", isOn: .init(
get: { isDisplayed },
set: {
isDisplayed = $0
print("changed")
}
))
Run Code Online (Sandbox Code Playgroud)
这就是我编码的方式:
Toggle("Title", isOn: $isDisplayed)
.onReceive([self.isDisplayed].publisher.first()) { (value) in
//Action code here
}
Run Code Online (Sandbox Code Playgroud)
更新代码(Xcode 12、iOS14):
Toggle("Enabled", isOn: $isDisplayed.didSet { val in
//Action here
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27360 次 |
| 最近记录: |