2015-05-29 66 views
0

我有一個父類和一個子類。父母對孩子有很強的參考,孩子對父母有一個無與倫比的參考。在父母的DEINIT,我希望孩子做一些清理,並涉及調用父:子對象在父對象的初始化期間是否可以引用其父對象?

class ViewController: UIViewController 
{ 
    override func viewDidLoad() 
    { 
     super.viewDidLoad() 

     let parent = Parent() 
    } 
} 

class Parent : NSObject 
{ 
    override init() 
    { 
     super.init() 

     child.doStuff() 
    } 

    deinit 
    { 
     child.doStuff() 
    } 

    lazy private var child : Child = Child(parent : self) 
} 

class Child : NSObject 
{ 
    init(parent : NSObject) 
    { 
     self.parent = parent 
    } 

    func doStuff() 
    { 
     println(self.parent) 
    } 

    deinit 
    { 

    } 

    private unowned var parent : NSObject 
} 

不幸的是,母公司的DEINIT過程中調用doStuff()導致系統崩潰,因爲它使用self.parent

libswiftCore.dylib`_swift_abortRetainUnowned: 
    0x111e91740 <+0>: leaq 0x1e6cd(%rip), %rax  ; "attempted to retain deallocated object" 
    0x111e91747 <+7>: movq %rax, 0x58612(%rip)  ; gCRAnnotations + 8 
    0x111e9174e <+14>: int3 
-> 0x111e9174f <+15>: nop  

據我所知,父母應該仍然存在,因爲父母的deinit尚未完成。然而,這個錯誤似乎表明,孩子不能再訪問其父母的引用。

任何人都可以對此有所瞭解嗎?

+0

你能告訴我們你是如何在你的情況下調用'deinit'嗎? – Unheilig

+0

我已經添加了'viewDidLoad'來顯示父級的init/deinit的上下文。 – JimmyB

回答

1

在這種情況下,無主(不安全)將做到這一點。 但我個人不會使用無主(不安全)的任何東西,但橋接Objective-C代碼。

如果可能的話,我會盡量避免需要從deinit()中調用child.doStuff(),如果可能的話。我有類似的情況,我簡單地添加了一個.unload()方法,我的代碼負責在需要時調用它。在上面的例子中,ViewController可以接受這個責任。

我想烏托邦的解決方案是,找到一種方法,其中的對象不是通過設計交織在一起,當然/如果可能的話。

卸載的實施例()方案:(I測試了它在終端REPL,因此沒有UIKit中)

import Foundation 

class ViewController { 
    let parent = Parent() 

    deinit { 
    parent.unload() 
    } 
} 

class Parent { 

    init() { 
    child.doStuff() 
    } 

    func unload() { 
    // Code used to be in deinit 
    child.doStuff() 
    } 

    lazy private var child : Child = Child(parent : self) 
} 

class Child { 

    init(parent : Parent) { 
    self.parent = parent 
    } 

    func doStuff() { 
    println(self.parent) 
    } 

    private unowned var parent : Parent 
} 

var vc:ViewController? = ViewController() 
vc = nil 
0

使用unowned(unsafe)修復了此問題。一般來說,這看起來相當危險,但在這種情況下,這是可以的,因爲在孩子存在的時候父母會保證存在。

1

如何父本身傳遞作爲參數傳遞給孩子的方法需要它:

class Parent 
{ 
    deinit 
    { 
     child.doStuff(self) 
    } 
} 

class Child 
{ 
    func doStuff(parent) 
    { 
     println(parent) 
    } 
} 
+0

好的建議!將嘗試。 – JimmyB