比方说,我有一个模型,用String
类型的属性color
称为Car
:商店参考斯威夫特
class Car {
var color: String?
}
现在,我有另一个类称为Interface
,我想用它来修改数值的color
财产Car
。要做到这一点,我想以某种方式结合color
至Interface
的属性,如key
:
class Interface {
var storedKey: String?
func bind(key: String?) {
self.storedKey = key
}
}
用法:
let corolla = Car()
corolla.color = "green"
let interface = Interface()
interface.bind(key: &corolla.color)
interface.storedKey = "blue"
print(corolla.color) // still "green"! :(
因为字符串值类型(结构)在这种方法失败Swift,因此bind
函数获得corolla.color
的副本,而不是参考。这意味着修改storedKey
的interface
对corolla.color
的值没有影响。
如果我们将inout
添加到如下所示的绑定函数中,我们基本上获得了传入的密钥的引用(it's actually copied in then copied out),但它只是作用于该函数的作用域。
func bind(key: inout String?) {
self.storedKey = key // assignment of value type is a copy! :/
}
结果是一样的,修改storedKey
对它所绑定的属性没有影响。
这可以归结为什么,我们可以在Swift中获得对struct的引用吗?
由于结构占用的内存空间,我们也许能够获得一个指向传递的关键,这里是工作(不正确)解决方案:
class Car {
var color: String?
}
let corolla = Car()
corolla.color = "green"
class Interface {
var storedKey: UnsafeMutablePointer<String?>?
func bind(_ key: inout String?) {
self.storedKey = withUnsafeMutablePointer(to: &key) { ptr in
return ptr
}
}
}
var interface = Interface()
interface.bind(&corolla.color)
interface.storedKey?.pointee = "blue" // :O it's... working?
print(corolla.color)
在我看来,这打破了至少两个语义规则在斯威夫特:
withUnsafeMutablePointer
通过&
传递一个实例的地址转换为该实例的类型为“”,仅在使用时才在之间提供关闭。按照the Swift docs:body的指针参数只对封闭的生命周期有效。不要将它从闭合物中脱出以供以后使用。
- 第二个问题是,这利用了Swift编译器优化,允许
bind
实际获得对key
的引用而不是副本。否则,指针不会获得对原始键的引用,而是获得对副本的引用。inout
参数通常使用称为拷入拷贝的行为来实现,其中参数的拷贝被传递给函数,可能被修改,然后被分配回原始参数。 As per the docs,有一个优化,如果参数是存储的属性,则在函数体内部和外部使用相同的存储位置。这使得我们的指针可以获得对原始String结构的引用,而不是副本,从而可以工作。作为优化,当参数是存储在内存中物理地址的值时,函数体内部和外部都使用相同的内存位置。
有什么办法来存储为String
这样一个结构的参考?还是我在疯狂的追逐?编辑1:另外,我不能控制Car
的属性。
比较[斯威夫特:通过指针访问计算属性](http://stackoverflow.com/q/42798354/2976878) - 你可能只想要一个闭包。 – Hamish
您可能正在寻找“镜头”:http://chris.eidhof.nl/post/lenses-in-swift/ –