[英]Store reference to struct in Swift
Let's say I have a model, called Car
with a property color
of type String
: 假设我有一个名为
Car
的模型,其color
为String
类型:
class Car {
var color: String?
}
Now, I have another class called Interface
that I wish to use to modify the value of the color
property of Car
. 现在,我有另一个名为
Interface
类,希望用于修改Car
的color
属性的值。 To do this, I'd like to somehow bind color
to a property of Interface
, such as key
: 为此,我想以某种方式将
color
绑定到Interface
的属性,例如key
:
class Interface {
var storedKey: String?
func bind(key: String?) {
self.storedKey = key
}
}
Usage: 用法:
let corolla = Car()
corolla.color = "green"
let interface = Interface()
interface.bind(key: &corolla.color)
interface.storedKey = "blue"
print(corolla.color) // still "green"! :(
This approach fails because strings are value types (structs) in Swift, so the bind
function gets a copy of corolla.color
, not a reference. 这种方法失败了,因为字符串是Swift中的值类型(结构),因此
bind
函数将获得corolla.color
的副本,而不是引用。 This means modifying storedKey
of interface
has no effect on the value of corolla.color
. 这意味着修改
storedKey
的interface
对的值没有影响corolla.color
。
If we add inout
to the binding function as shown below, we basically obtain a reference to the key passed in ( it's actually copied in then copied out ), but it only lasts for the scope of the function. 如果我们按如下所示将
inout
添加到绑定函数中,则基本上可以得到对传入的键的引用( 它实际上是复制进来的,然后复制出来的 ),但是它仅在函数作用域内有效。
func bind(key: inout String?) {
self.storedKey = key // assignment of value type is a copy! :/
}
The results are the same, modifying storedKey
has no effect on the property it is bound to. 结果是相同的,修改
storedKey
对其绑定的属性没有影响。
What this boils down to is, can we obtain a reference to a struct in Swift? 归结为是,我们可以在Swift中获得对结构的引用吗?
Since structs occupy space in memory, we may be able to obtain a pointer to the key passed in, here is a working (incorrect) solution: 由于结构占用了内存空间,因此我们可以获取指向传入键的指针,这是一个可行的(不正确)解决方案:
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)
As I see it, this breaks at least two semantic rules in Swift: 如我所见,这至少破坏了Swift中的两个语义规则:
withUnsafeMutablePointer
converts the address of an instance passed in via &
to a UnsafeMutablePointer
of that instances' type, to be used only within the provided closure. withUnsafeMutablePointer
会将通过&
传入的实例的地址转换为该实例类型的UnsafeMutablePointer
, 仅在提供的闭包中使用。 As per the Swift docs : 根据Swift文档 :
The pointer argument to body is valid only for the lifetime of the closure.
指向body的指针参数仅在关闭的有效期内有效。 Do not escape it from the closure for later use.
请勿将其从封盖中逸出以备后用。
bind
to actually obtain a reference to key
instead of a copy. bind
实际获取对key
的引用而不是副本。 Otherwise, the pointer would not obtain a reference to the original key, but to a copy. inout
parameters are normally implemented using a behavior known as copy-in copy-out, whereby a copy of the argument is passed in to the function, possibly modified, and then assigned back to the original argument. inout
参数通常使用一种称为copy-in copy-out的行为来实现,从而将参数的副本传递到函数中,并可以对其进行修改,然后将其赋值回原始参数。 As per the docs , there is an optimization whereby if the argument is a stored property, the same memory location is used both inside and outside the function body. As an optimization, when the argument is a value stored at a physical address in memory, the same memory location is used both inside and outside the function body.
作为优化,当参数是存储在内存中物理地址上的值时,在函数体内外都使用相同的存储位置。
Is there any way to store a reference to a struct such as String
? 有什么方法可以存储对诸如
String
的结构的引用? Or am I on a wild goose chase? 还是我在追逐野鹅?
Edit 1: Also, I have no control of the types of Car
's properties. 编辑1:另外,我无法控制
Car
的属性类型。
You can't get a reference to your struct as you already researched. 您已经研究过,因此无法获得对结构的引用。
What you can do is use a Box class and pass that around. 您可以做的是使用Box类并传递它。
Then you would use the Box everywhere and access its struct property wherever needed. 然后,您将在任何地方使用Box并在需要时访问其struct属性。
Something like: 就像是:
class Box<T> {
var value: T
init(value: T) {
self.value = value
}
}
and use it with a Car 并与汽车一起使用
let boxedCar = Box(value: Car(...))
You can share references to this box and always access the car through the value property 您可以共享对此框的引用,并始终通过value属性访问汽车
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.