Another way to address this might be by allowing property behaviors, a feature
proposed in
https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md
to allow for factoring out property implementations, could also apply to
`case` declarations. "Weak" and "unowned" could be considered to be property
behaviors once we have them, so you'd write something like:
class Foo {
var parent: Foo?
behavior weak
}
to define a property with "weak" behavior. We could potentially allow you to
apply behaviors to 'case' associated values too:
enum ParentChild {
case Parent(Parent) behavior unowned
case Child(Parent) behavior unowned
}
-Joe
> On May 3, 2016, at 8:07 AM, Marc Prud'hommeaux via swift-evolution
> <[email protected]> wrote:
>
>
> The following code currently has a retain cycle and memory leak:
>
> enum ParentChild {
> case SonOf(Parent)
> case DaughterOf(Parent)
> }
>
> class Parent {
> lazy var son: Child = Child(parentChild: .SonOf(self))
> lazy var daughter: Child = Child(parentChild: .DaughterOf(self))
> deinit { print("deinit Parent") }
> }
>
> class Child {
> var parentChild: ParentChild
> init(parentChild: ParentChild) {
> self.parentChild = parentChild
> }
> deinit { print("deinit Child") }
> }
>
>
> do {
> let parent = Parent()
> parent.son
> parent.daughter
> }
>
>
> Child.parentChild cannot be declared unowned because ParentChild is a value
> type. I propose adding the ability to declare the reference storage class for
> an enum's associated value, like so:
>
> enum ParentChild {
> case SonOf(unowned Parent)
> case DaughterOf(unowned Parent)
> }
>
> The only current alternative is to have some intermediate reference type that
> itself holds the reference, akin to the old "Box" type that we used to use to
> work around enum limitations. E.g., this is our current cumbersome
> work-around:
>
> /// An unowned reference to a value, which is useful for maintaining
> parent-child relations through value types like enums
> public struct UnownedRef<T: AnyObject> {
> public unowned let value: T
> public init(_ value: T) { self.value = value }
> }
>
> enum ParentChild {
> case SonOf(UnownedRef<Parent>)
> case DaughterOf(UnownedRef<Parent>)
> }
>
>
> class Parent {
> lazy var son: Child = Child(parentChild: .SonOf(UnownedRef(self)))
> lazy var daughter: Child = Child(parentChild:
> .DaughterOf(UnownedRef(self)))
> deinit { print("deinit Foo") }
> }
>
> class Child {
> var parentChild: ParentChild
> init(parentChild: ParentChild) {
> self.parentChild = parentChild
> }
>
> deinit { print("deinit Child") }
> }
>
> The storage type of an enum would, of course, be limited to reference types,
> and when the storage class is weak, it would require that the stored type be
> Optional, just like when declaring a weak variable.
>
> What do people think?
>
> -Marc
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution