我的申請有問題。我正在嘗試切換一個開關,當這個開關被切換時,所有其他開關都被切換到關閉。我嘗試過使用 onChange 方法。此方法適用于 2 個開關,但不適用于 3 個或更多?
這是我嘗試的代碼:
import SwiftUI
import ToastUI
struct ContentView: View {
@State var generatedNumber : Int = 0
@State var allNumbers : Bool = true
@State var evensOnly : Bool = false
@State var oddsOnly : Bool = false
var body: some View {
VStack {
Text("Your genenerated number:")
.font(.bold(.title)())
Text("\(generatedNumber)")
.font(.bold(.custom("Generated Number Size", size: 60))())
.foregroundColor(.cyan)
VStack{
Toggle("All numbers", isOn: $allNumbers)
.tint(.cyan)
.onChange(of: allNumbers) { newValue in
//When toggled, turn other switches off, but leave this one on
evensOnly = !newValue
oddsOnly = !newValue
}
Toggle("Even numbers only", isOn: $evensOnly)
.tint(.cyan)
.onChange(of: evensOnly) { newValue in
allNumbers = !newValue
oddsOnly = !newValue
}
Toggle("Odd numbers only", isOn: $oddsOnly)
.tint(.cyan)
.onChange(of: oddsOnly) { newValue in
allNumbers = !newValue
evensOnly = !newValue
}
}.padding(30)
.toggleStyle(.switch)
}
}
}
這就是我得到的:

一次只能打開一個開關,如果切換另一個開關,則關閉另外兩個。執行此操作時的 onChange 方法狀態:“操作嘗試每幀更新多次。” 這是否意味著兩個@State 重新加載試圖在執行時間太接近彼此?請幫我
uj5u.com熱心網友回復:
正如第一條評論已經說過的那樣,您有一個保留周期。為了實作您的目標,有很多解決方案。但是,我會這樣做(參見代碼片段)使用 MVVM 模式來實作它。
struct ContentView: View {
@State var generatedNumber : Int = 0
@StateObject var viewModel: ContentViewModel = .init()
var body: some View {
VStack {
Text("Your genenerated number:")
.font(.bold(.title)())
Text("\(generatedNumber)")
.font(.bold(.custom("Generated Number Size", size: 60))())
.foregroundColor(.cyan)
VStack {
Toggle("All numbers", isOn: $viewModel.allNumbers)
.tint(.cyan)
Toggle("Even numbers only", isOn: $viewModel.evensOnly)
.tint(.cyan)
Toggle("Odd numbers only", isOn: $viewModel.oddsOnly)
.tint(.cyan)
}.padding(30)
.toggleStyle(.switch)
}
}
}
class ContentViewModel: ObservableObject {
@Published var allNumbers : Bool = true
@Published var evensOnly : Bool = false
@Published var oddsOnly : Bool = false
private var store: [AnyCancellable] = []
init() {
$allNumbers
.sink(receiveValue: {
guard $0 else { return }
self.evensOnly = false
self.oddsOnly = false
})
.store(in: &store)
$evensOnly
.sink(receiveValue: {
guard $0 else { return }
self.allNumbers = false
self.oddsOnly = false
})
.store(in: &store)
$oddsOnly
.sink(receiveValue: {
guard $0 else { return }
self.allNumbers = false
self.evensOnly = false
})
.store(in: &store)
}
}
uj5u.com熱心網友回復:
這是一個涉及陣列的稍微健壯的答案,因此現在您有了動態toggle視圖。
enum numbersOptions: String {
case all = "All numbers"
case even = "Even numbers"
case odd = "Odd numbers only"
}
struct OptionItem: Identifiable, Equatable {
let id = UUID()
let option: numbersOptions
var isOn: Bool = false
}
struct ToggleTest: View {
@State var generatedNumber : Int = 0
@State var options = [OptionItem(option: .all, isOn: true), OptionItem(option: .even), OptionItem(option: .odd)]
var body: some View {
VStack {
Text("Your genenerated number:")
.font(.bold(.title)())
Text("\(generatedNumber)")
.font(.bold(.custom("Generated Number Size", size: 60))())
.foregroundColor(.cyan)
VStack{
ForEach($options) { $option in
Toggle(option.option.rawValue, isOn: $option.isOn)
.tint(.cyan)
.onChange(of: option) { updated in
if updated.isOn {
self.options = self.options.map({
var optionItem = $0
optionItem.isOn = $0.id == updated.id
return optionItem })
// ANY UPDATED BASED ON THE SELECTED ITEM
switch updated.option {
case .all:
print("all seleted")
case .even:
print("eve seleted")
case .odd:
print("odd seleted")
}
}
}
}
}
.padding(30)
.toggleStyle(.switch)
}
}
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/521058.html
標籤:迅速迅捷
下一篇:如何在異步方法中實作執行緒安全?
