2016-03-02 41 views
1

我已經建立了一棵樹,樹的節點是這樣的:當引用weak-ref變量時,是否應該使用'weak'來指定計算屬性?

class TreeNode { 
    var isRoot: Bool { 
     return parentNode == nil 
    } 
    var childNodes = [TreeNode]() 
    weak var parentNode: TreeNode? 
    private weak var _rootNodeCache: TreeNode? 
    var rootNode: TreeNode? { 
     return _rootNodeCache 
    } 
    private func updateRootCache(node: TreeNode) { 
     ...// Implementation doesn't matter. 
    } 
} 

我想請問應該計算財產rootNodeweak指定? 看起來沒問題,但我恐怕會造成泄漏。

+0

據說計算屬性不存儲任何對象。令我困惑的是:如果沒有弱指示符,'''_rootNodeCache''被視爲通過''''rootNode'''強引用?如果是這樣,是否有泄漏? – AntiMoron

+0

Apple文檔指出計算屬性不存儲值,因此'_rootNodeCache'不會被視爲通過'rootNode'的強引用,因爲'_rootNodeCache'被聲明爲弱。所以不會有泄漏,並且不需要指定'rootNode'弱。 – carbo18

回答

2

當你有循環引用時,你只需要使用weak。我知道你有一個(父母)TreeNodeTreeNode孩子。父母對每個孩子都有很強的參考意義,因此從孩子回到父母的任何引用必須是weak或者兩者都不會被破壞。您通過將parentNode標記爲弱而完成此操作。

rootNode的情況下,您只需要擔心它返回的內容。由於它返回的結果是_rootNodeCache,因此不會有循環引用。你可以用下面的代碼來證明這一點。從rootNode添加或刪除弱點沒有區別。但是,從_rootNodeCacheparentNode中刪除弱結果會導致循環引用和deinit不被調用。

class TreeNode { 
    var name: String = "" 
    var childNodes = [TreeNode]() 
    weak var parentNode: TreeNode? 
    private weak var _rootNodeCache: TreeNode? 
    var rootNode: TreeNode? { 
     return _rootNodeCache 
    } 
    init(_ name: String, _ root: TreeNode?, _ parent: TreeNode?) { 
     self.name = name 
     _rootNodeCache = root 
     parentNode = parent 
     if let parent = parent { 
      print("Adding \(name) to \(parent.name)") 
      parent.childNodes.append(self) 
     } 
    } 
    deinit { 
     print("deinit \(name) \(childNodes.count) children") 
    } 
    func show() { 
     print("\(name) has \(childNodes.count) children") 
     for child in childNodes { 
      child.show() 
     } 
    } 
} 

func addChildren(root: TreeNode) { 
    let child = TreeNode("child", root, root) 
    TreeNode("grandchild", root, child) 
} 

var root: TreeNode? = TreeNode("root", nil, nil) 
addChildren(root!) 
root!.show() 
root = nil 
相關問題