使自定义 get {} set{} 像动态 proxy/shortcut 一样对数组中的不同对象起作用。 (斯威夫特用户界面)
Making custom get {} set{} to work like dynamic proxy/shortcut to different objects in Array. (SwiftUI)
我正在尝试实现类似绑定的双向功能。
我有一个模型,其中包含可识别的 Item
数组,var selectedID
持有选定 Item
的 UUID,而 var proxy
具有 get{}
通过 UUID 查找数组中的项目并 returns 它。
虽然 get{}
运行良好,但我无法弄清楚如何通过引用代理使 proxy
可变以更改所选 Item
的值。
我已经尝试实施 set{}
但没有任何效果。
import SwiftUI
var words = ["Aaaa", "Bbbb", "Cccc"]
struct Item: Identifiable {
var id = UUID()
var word: String
}
class Model: ObservableObject {
@Published var items: [Item] = [Item(word: "One"), Item(word: "Two"), Item(word: "Three")]
@Published var selectedID: UUID?
var proxy: Item? {
set {
// how to set one property of Item?, but not the whole Item here?
}
get {
let index = items.firstIndex(where: { [=11=].id == selectedID })
return index != nil ? items[index!] : nil
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
VStack {
// monitoring
MonitorkVue(model: model)
//selections
HStack {
ForEach(model.items.indices, id:\.hashValue) { i in
SelectionVue(item: $model.items[i], model: model)
}
}
}.padding()
}
}
struct MonitorkVue: View {
@ObservedObject var model: Model
var body: some View {
VStack {
Text(model.proxy?.word ?? "no proxy")
// 3rd: cant make item change by referring to proxy
// in order this to work, proxy's set{} need to be implemented somehow..
Button {
model.proxy?.word = words.randomElement()!
} label: {Text("change Proxy")}
}
}
}
struct SelectionVue: View {
@Binding var item: Item
@ObservedObject var model: Model
var body: some View {
VStack {
Text(item.word).padding()
// 1st: making selection
Button {
model.selectedID = item.id } label: {Text("SET")
}.disabled(item.id != model.selectedID ? false : true)
// 2nd: changing item affects proxy,
// this part works ok
Button {
item.word = words.randomElement()!
}label: {Text("change Item")}
}
}
}
设置选择后,您可以随机化项目,代理将 return 新值。
但是当更改 module.proxy.word = "Hello"
会影响选定的 Item
?
时,如何使它以相反的方式工作
有谁知道如何制作这条双向捷径?
谢谢
这是更正和一些修正:
struct Item: Identifiable {
var id = UUID()
var word: String
}
class Model: ObservableObject {
@Published var items: [Item] = [Item(word: "One"), Item(word: "Two"), Item(word: "Three")]
@Published var selectedID: UUID?
var proxy: Item? {
get {
if let unwrappedIndex: Int = items.firstIndex(where: { value in (selectedID == value.id) }) { return items[unwrappedIndex] }
else { return nil }
}
set(newValue) {
if let unwrappedItem: Item = newValue {
if let unwrappedIndex: Int = items.firstIndex(where: { value in (unwrappedItem.id == value.id) }) {
items[unwrappedIndex] = unwrappedItem
}
}
}
}
}
我正在尝试实现类似绑定的双向功能。
我有一个模型,其中包含可识别的 Item
数组,var selectedID
持有选定 Item
的 UUID,而 var proxy
具有 get{}
通过 UUID 查找数组中的项目并 returns 它。
虽然 get{}
运行良好,但我无法弄清楚如何通过引用代理使 proxy
可变以更改所选 Item
的值。
我已经尝试实施 set{}
但没有任何效果。
import SwiftUI
var words = ["Aaaa", "Bbbb", "Cccc"]
struct Item: Identifiable {
var id = UUID()
var word: String
}
class Model: ObservableObject {
@Published var items: [Item] = [Item(word: "One"), Item(word: "Two"), Item(word: "Three")]
@Published var selectedID: UUID?
var proxy: Item? {
set {
// how to set one property of Item?, but not the whole Item here?
}
get {
let index = items.firstIndex(where: { [=11=].id == selectedID })
return index != nil ? items[index!] : nil
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
VStack {
// monitoring
MonitorkVue(model: model)
//selections
HStack {
ForEach(model.items.indices, id:\.hashValue) { i in
SelectionVue(item: $model.items[i], model: model)
}
}
}.padding()
}
}
struct MonitorkVue: View {
@ObservedObject var model: Model
var body: some View {
VStack {
Text(model.proxy?.word ?? "no proxy")
// 3rd: cant make item change by referring to proxy
// in order this to work, proxy's set{} need to be implemented somehow..
Button {
model.proxy?.word = words.randomElement()!
} label: {Text("change Proxy")}
}
}
}
struct SelectionVue: View {
@Binding var item: Item
@ObservedObject var model: Model
var body: some View {
VStack {
Text(item.word).padding()
// 1st: making selection
Button {
model.selectedID = item.id } label: {Text("SET")
}.disabled(item.id != model.selectedID ? false : true)
// 2nd: changing item affects proxy,
// this part works ok
Button {
item.word = words.randomElement()!
}label: {Text("change Item")}
}
}
}
设置选择后,您可以随机化项目,代理将 return 新值。
但是当更改 module.proxy.word = "Hello"
会影响选定的 Item
?
有谁知道如何制作这条双向捷径? 谢谢
这是更正和一些修正:
struct Item: Identifiable {
var id = UUID()
var word: String
}
class Model: ObservableObject {
@Published var items: [Item] = [Item(word: "One"), Item(word: "Two"), Item(word: "Three")]
@Published var selectedID: UUID?
var proxy: Item? {
get {
if let unwrappedIndex: Int = items.firstIndex(where: { value in (selectedID == value.id) }) { return items[unwrappedIndex] }
else { return nil }
}
set(newValue) {
if let unwrappedItem: Item = newValue {
if let unwrappedIndex: Int = items.firstIndex(where: { value in (unwrappedItem.id == value.id) }) {
items[unwrappedIndex] = unwrappedItem
}
}
}
}
}