我有两个具有一对一关系的CoreData实体。我想基于此实体创建结构。 我的代码:
struct DetailedPin { var pin: Pin? } struct Pin { var detailedPin: DetailedPin? }
但我收到一个错误:Value type 'DetailedPin' cannot have a stored property that references itself。和Pin结构相同的错误。我该如何处理?谢谢。
Value type 'DetailedPin' cannot have a stored property that references itself
Pin
问题在于,一个inline Optional存储其Wrapped值(有关此信息,请参见Mike Ash的精彩博客文章)–意味着一个Optional实例(无论是否nil存在)将至少占用与所需类型相同的内存量存储在它的.some大小写(Wrapped类型)中。
Optional
Wrapped
nil
.some
因此,由于您的Pin结构具有type属性DetailedPin?,并且type DetailedPin属性,Pin?因此需要无限存储才能内联存储这些值。
DetailedPin?
DetailedPin
Pin?
因此,解决方案只是添加一个间接层。一种这样做的方法是按照@dfri的建议进行make Pin和/或DetailedPin引用类型(即aclass)。
class
但是,如果您希望保留Pinand 的值语义DetailedPin,则一种选择是创建一个由类实例支持的包装器类型,以提供必要的间接寻址:
/// Provides indirection for a given instance. /// For value types, value semantics are preserved. struct Indirect<T> { // Class wrapper to provide the actual indirection. private final class Wrapper { var value: T init(_ value: T) { self.value = value } } private var wrapper: Wrapper init(_ value: T) { wrapper = Wrapper(value) } var value: T { get { return wrapper.value } set { // Upon mutation of value, if the wrapper class instance is unique, // mutate the underlying value directly. // Otherwise, create a new instance. if isKnownUniquelyReferenced(&wrapper) { wrapper.value = newValue } else { wrapper = Wrapper(newValue) } } } }
现在,您可以只将Indirect包装器用于您的structs属性中的一个(或两个):
Indirect
struct DetailedPin { private var _pin = Indirect<Pin?>(nil) // Convenience computed property to avoid having to say ".value" everywhere. var pin: Pin? { get { return _pin.value } set { _pin.value = newValue } } } struct Pin { var detailedPin: DetailedPin? var foo: String } var d = DetailedPin() var p = Pin(detailedPin: d, foo: "foo") d.pin = p // testing that value semantics are preserved... var d1 = d d1.pin?.foo = "bar" print(d.pin?.foo as Any) // Optional("foo") print(d1.pin?.foo as Any) // Optional("bar")