在这段代码中,我想改变两个选择器值,当它们是相同的,以保持这两个彼此不同。我尝试使用swap,但是不能正常工作。
例如:当第一个选择器值为1,第二个选择器值为2时,当我试图将第二个值更改为"1"时,值立即更改为1,第一个选择器变为2 !
struct ContentView: View {
@State private var list = ["one","two","three","four","five"]
@State private var from: String = "one"
@State private var from: String = "two"
var body: some View {
VStack {
Picker("",selection: $from) {
ForEach(list, id: .self) { item in
Text(item)
}
}
.pickerStyle(.menu)
.padding(.trailing)
.onChange(of: from) { newValue in
if newValue == to {
(to,from) = (from, to)
}
}
Picker("",selection: $to) {
ForEach(list, id: .self) { item in
Text(item)
}
}
.pickerStyle(.menu)
.padding(.trailing)
}
}
}
我在应用程序的另一部分使用这个元组解决方案,但在这一部分不起作用:
(from, to) = (to, from)
我怎么能执行立即交换这两个值时,例如去相同的从?
我认为缺少了一种联系。你国家
如果我对第一个拾取器的更改导致两个拾取器相等,那么立即交换它们!
如果你交换两个相等的值,你会得到两个相等的值。
假设:
看来你想要的是解决方案的标准面试问题交换2值。
给定x=1, y=2。交换值
方法是
let temp = y //holds a value
y = x //starts swap
x = temp //finishes swap
现在结果是y=1 and x=2
当您交换值时,您需要temp
变量来保存其中一个的值。
现在,如果我们回到你的语句,错误就在等待两个值相等。
当您单击新项时,将立即进行更改,因此无法检索先前的值。
x = newValue or y = newValue
实现"切换"的唯一方法就是确定是否有需要调换之前的"真相来源";变化。
- 选择新值
- 检查是否需要交换
- 交换真值的来源
- 告诉SwiftUI有更新
您可以在SwiftUI中使用ObservableObject
class AutoPickerVM: ObservableObject{
///Variable that holds the value for From - Source of truth
private var storeFrom: String = "one"
///Processes the changes between the pickers and triggers view updates
var from: String {
get{
storeFrom
}
set{
if newValue == to{
//Take the value that is currently there
let curTo = to
//Start swapping
storeTo = storeFrom
//Place the previous value
storeFrom = curTo
}else{
storeFrom = newValue
}
objectWillChange.send()
}
}
///Variable that holds the value for to - Source of truth
private var storeTo: String = "two"
///Processes the changes between the pickers and triggers view updates
var to: String {
get{
storeTo
}
set{
if newValue == from{
//Take the value that is currently there
let curFrom = from
//Start swapping
storeFrom = storeTo
//Place the previous value
storeTo = curFrom
}else{
storeTo = newValue
}
objectWillChange.send()
}
}
init(){}
}
那么你的View
看起来像这样
struct AutoPicker: View {
@StateObject var vm: AutoPickerVM = .init()
@State private var list = ["one","two","three","four","five"]
var body: some View {
VStack {
Picker("",selection: $vm.from) {
ForEach(list, id: .self) { item in
Text(item)
}
}
.pickerStyle(.menu)
.padding(.trailing)
Picker("",selection: $vm.to) {
ForEach(list, id: .self) { item in
Text(item)
}
}
.pickerStyle(.menu)
.padding(.trailing)
}
}
}
仍然不能100%确定你要做什么,但它可能是这样的,如下面的示例代码所示,使用帮助变量:
struct ContentView: View {
@State private var list = ["one","two","three","four","five"]
@State private var from: String = "one"
@State private var to: String = "two"
@State private var prevFrom: String = "one"
@State private var prevTo: String = "two"
var body: some View {
VStack {
Picker("",selection: $from) {
ForEach(list, id: .self) { item in
Text(item)
}
}
.pickerStyle(.menu)
.padding(.trailing)
.onChange(of: to) { _ in
if to == from {
from = prevTo
}
prevTo = to
}
.onChange(of: from) { _ in
if to == from {
to = prevFrom
}
prevFrom = from
}
Picker("",selection: $to) {
ForEach(list, id: .self) { item in
Text(item)
}
}
.pickerStyle(.menu)
.padding(.trailing)
}
}
}