A one to one relationship between two entities is only valid if at least one of the connections between these entities is of reference type; for two pure value types, their one to one relationsship will become a recursive one.
Say you create an object of the value type DetailedPin
. It contains an instance property (pin
) of the value type Pin
, which means this instance property is part of the value that is the instance of DetailedPin
. Now, the instance property pin
of and instance of DetailedPin
, is of the value type Pin
, which itself contains an instance property (detailedPin
) of value type DetailedPin
. This instance member detailedPin
is, again, _a part of the value that is the instance pin
), but again, detailedPin
itself owns a value of type pin
, and so the recursive dance continues ...
You can circumvent this by turning one of your structures into a reference type (class
):
struct DetailedPin {
var pin: Pin?
}
class Pin {
var detailedPin: DetailedPin?
}
// or
class DetailedPin {
var pin: Pin?
}
struct Pin {
var detailedPin: DetailedPin?
}
Note that the recursive relationship covered above is not directly related to ARC (automatic reference counting) or strong reference cycles, but the fact that the value of a value type instance is the instance itself and the value of all value type (sub-)properties it contains (as well as the reference to all reference type (sub-)properties it contains).
Just take care if you choose to let both your one to one entities be reference types: in this case you must make sure that one of the references between the two types are weak
. E.g.:
class DetailedPin {
weak var pin: Pin?
}
class Pin {
var detailedPin: DetailedPin?
}
// or
class DetailedPin {
var pin: Pin?
}
class Pin {
weak var detailedPin: DetailedPin?
}
In case you leave out weak
above (i.e., let both refer to each other by the default strong references), you will have a strong reference cycle between the two instances referring to each other
class DetailedPin {
var pin: Pin?
deinit { print("DetailedPin instance deinitialized") }
}
class Pin {
var detailedPin: DetailedPin?
deinit { print("Pin instance deinitialized") }
}
func foo() {
let pin = Pin()
let detailedPin = DetailedPin()
pin.detailedPin = detailedPin
detailedPin.pin = pin
}
foo() // no deinit called