gpt4 book ai didi

swift - 修改深度嵌套结构的简单方法

转载 作者:行者123 更新时间:2023-12-04 13:33:02 24 4
gpt4 key购买 nike

我越来越熟悉 Swift 结构的“写时复制”行为。我认为这是一个非常好的方法来避免必须管理结构的引用,但是在处理深度嵌套的结构时它有点麻烦。
如果要更新深度嵌套的值,则需要该值的直接路径,以便可以在一行中修改它:

myStruct.nestedArray[index].nestedValue = 1
编译器会复制 myStruct.nestedArray[index]并设置 nestedValue1在那个新值上。然后它会复制 myStruct.nestedArray并将新值设置为 index .然后它会复制 myStruct并用具有上述所有更改的新值替换先前的值。
这工作得很好,而且很酷,您可以使用一行代码完成此操作,而不必担心引用 myStruct 的任何内容。和它的 child 之前。但是,如果解析值的路径涉及更复杂的逻辑,则逻辑会变得更加冗长:
struct MyStruct {
var nestedEnum: MyEnum
}

enum MyEnum {
case one([NestedStruct])
case two([NestedStruct])
}

struct NestedStruct {
var id: Int
var nestedValue: Int
}

var myStruct = MyStruct(nestedEnum: .one([NestedStruct(id: 0, nestedValue: 0)]))
if case .one(var nestedArray) = myStruct.nestedEnum {
if let index = nestedArray.firstIndex(where: { $0.id == 0 }) {
nestedArray[index].nestedValue = 1
myStruct.nestedEnum = .one(nestedArray)
}
}
理想情况下,您可以执行以下操作:
if case .one(var nestedArray) = myStruct.nestedEnum {
if var nestedStruct = nestedArray.first(where: { $0.id == 0 }) {
nestedStruct.nestedValue = 1
}
}
但是一旦 nestedStruct.nestedValue设置后, nestedStruct 的新值被吞下。
如果 Swift 有办法使用 inout,那就太好了。函数之外的语义,所以我可以“引用”到 nestedArray然后 nestedStruct在其中设置内部 nestedValue ,导致副本传播回 myStruct就像我能够在一行中完成一样。
有没有人有任何处理深层嵌套结构的好方法可以帮助我?还是我只需要忍受上面第二个示例中的模式?

最佳答案

我最终得出的解决方案是非常针对 SwiftUI 的,但它可能适用于其他框架。
基本上,我没有让一个单一的顶级方法负责深度更新结构,而是安排我的 SwiftUI 层次结构来镜像结构的结构,并通过了 Binding向下只是管理层次结构的一个节点。
例如,鉴于我上面定义的结构:

struct MyStruct {
var nestedEnum: MyEnum
}

enum MyEnum {
case one([NestedStruct])
case two([NestedStruct])
}

struct NestedStruct {
var id: Int
var nestedValue: Int
}
我可以这样做:
struct MyStructView: View {
@Binding var myStruct: MyStruct

var body: some View {
switch myStruct.nestedEnum {
case .one: OneView(array: oneBinding)
case .two: TwoView(array: twoBinding)
}
}

var oneBinding: Binding<[NestedStruct]> {
.init(
get: {
if case .one(array) = myStruct.nestedEnum {
return array
}
fatalError()
},
set: { myStruct.nestedEnum = .one($0) }
)
}

var twoBinding: Binding<[NestedStruct]> { /* basically the same */ }
}

struct OneView: View {
@Binding var array: [NestedStruct]

var body: some View {
ForEach(0..<array.count, id: \.self) {
NestedStructView(nestedStruct: getBinding($0))
}
}

func getBinding(_ index: Int) -> Binding<NestedStruct> {
.init(get: { array[index] }, set: { array[index] = $0 })
}
}

struct NestedStructView: View {
@Binding var nestedStruct: NestedStruct

var body: some View {
NumericInput(title: "ID: \(nestedStruct.id)", value: valueBinding)
}

var valueBinding: Binding<Int> {
.init(get: { nestedStruct.value }, set: { nestedStruct.value = $0 })
}
}
唯一令人讨厌的一点是,构造 Binding 可能有点冗长。手动。我希望 SwiftUI 有一些用于嵌套的语法 Binding来自 Binding包含数组或结构。

关于swift - 修改深度嵌套结构的简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63865952/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com