0

In my iOS app I have

class Node {
    var value: String
    var isExpanded: Bool
    var children: [Node] = []

    private var flattenElementsCache: [Node]!

    // init methods

    var flattenElements: [Node] {
        if let cache = flattenElementsCache {
            return cache
        }
        flattenElementsCache = []
        flattenElementsCache.append(self) // (1) <-- Retain Cycle???
        if isExpanded {
            for child in children {
                flattenElementsCache.append(contentsOf: child.flattenElements)
            }
        }
        return flattenElementsCache;
    }
}

With Instruments, I've observed some memory leaks and I think the problem is in line indicated by (1).

Could anyone explain to me if it generates a retain cycle? If yes, how do you solve it?

Giorgio
  • 1,973
  • 4
  • 36
  • 51

2 Answers2

0

It does indeed create a retain cycle: your Node retains a reference to itself in flattenElementsCache.

You can delete the line marked by (1), and instead change the loop to:

for child in children {
    flattenElementsCache.append(child)
    flattenElementsCache.append(contentsOf: child.flattenElements)
}
Yonat
  • 4,382
  • 2
  • 28
  • 37
0

Obviously, to solve it use weak reference instead of strong.

class Node {
    var links: [Node?] = []
    init() {
        weak var weakSelf = self
        links.append(weakSelf)
    }
}

but I'm not sure whether there reference cycle appears

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194