如果我想将视图控制器的状态表示为一个结构体,然后实现一个撤销机制,那么我应该如何改变(比如说)结构体上的一个属性,同时获得前一个状态的副本?
struct A {
let a: Int
let b: Int
init(a: Int = 2, b: Int = 3) {
self.a = a
self.b = b
}
}
let state = A()
现在我想要一个state
的副本,但是b = 4。我怎样才能做到这一点,而不构造一个新的对象,也不必为每个属性指定一个值?
6条答案
按热度按时间eiee3dmh1#
注意,当你为 constants
a
和b
使用占位符值时,除了这个占位符,你不能用任何其他值构造A
的示例。改为编写初始化器。你也可以编写自定义方法来改变struct中的任何值:dgiusagp2#
这里的答案是荒谬的,特别是在struct的成员发生变化的情况下。
让我们了解一下Swift的工作原理。
当一个结构体被从一个变量设置到另一个变量时,该结构体被自动克隆到新变量中,即相同的结构体彼此不相关。
但是请记住,如果您计划更改struct中的成员,则必须将其标记为
var
,而不是let
。更多信息:https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
这很好,但是如果你仍然想在一行中复制和修改,那么就把这个函数添加到你的结构体中:
现在,前面的示例更改为:
我发现在很多结构体中添加"changing"会很痛苦,但是扩展会很棒:
用"Changeable"扩展你的结构体,你就有了"changing"函数。
对于"changing"函数方法,在"changing"函数的调用点(即
WritableKeyPath
类型)中指定的任何属性都应该在原始结构体中标记为var
,而不是let
。6gpjuf903#
如果你可以接受属性是可变的,这是一种替代方法,优点是它适用于每个结构体,并且在添加属性时不需要改变函数:
您还可以为此设置扩展名:
您也可以使用此命令来完成此操作,而无需任何附加代码:
如果你不介意新的结构体是可变的
fwzugrvs4#
我真的很喜欢@Shadow answer,但是我很难将它应用到结构体的字段可以为空的场景中,所以我决定使用builder模式,我的代码如下所示:
然后你可以这样使用它:
这样,我的结构体就真的是不可变的了,我可以快速地创建一个副本,并将它的一个或多个字段更改为
nil
或其他Int
ar5n3qh55#
我发现的最好的方法是编写一个初始化器方法,该方法接受要“复制”的相同类型的对象,然后具有可选参数来设置要更改的每个单独的属性。
可选的
init
参数允许您跳过任何希望在原始结构中保持不变的属性。zlhcx6iw6#
你可以像在Kotlin中那样为你的结构体写“copy”函数