2016-10-04 126 views
0

我有一個跟蹤貴金屬價格的程序。「試圖保留釋放對象」的循環引用

甲TransactionDTO具有無主參照一個AssetDTO

AssetDTO段:

public class AssetDTO: Equatable { 
var name: String! 
var transactions = [TransactionDTO]() 

TransactionDTO段:

unowned var asset: AssetDTO 

init(asset:AssetDTO, type:Constants.TransactionType) { 
    self.asset = asset 
    self.type = type 
    self.date = Date() 
} 

在UI控制器類,我遍歷在一個交易表,並顯示相關的金屬(金,銀等)。在我viewDidLoad中,表現出錯誤,我有以下代碼

var txs = [TransactionDTO]() 
    for asset in assetManager.findAllMetals() { 
     for tx in asset.transactions { 
      txs.append(tx) 
      print("the asset name for this is \(tx.asset.name)") 
     } 
    } 

    for tx in txs { 
     print("the asset name for this is \(tx.asset.name)") 
    } 

在第一循環中,資產版畫的名稱,在第二循環中,我得到:

libswiftCore.dylib`_swift_abortRetainUnowned: 
0x108d44cc0 <+0>: leaq 0x3058b(%rip), %rax  ; "attempted to retain deallocated object" 
0x108d44cc7 <+7>: movq %rax, 0x95f0a(%rip)  ; gCRAnnotations + 8 
0x108d44cce <+14>: int3 -> 0x108d44ccf <+15>: nop  

任何想法??

回答

1

unowned var asset: AssetDTO 

unowned是有效像weak刪除unowned,大概沒有別的引用的資產,所以它被釋放。但是,與weak不同,unowned不會爲您刪除變量。因此,你得到的錯誤。如果將其更改爲weak,則可能會發現它正在變爲零。

由於您想避免資產持有交易之間的循環參考,並且每個交易都有一個對資產的參考,所以後者應聲明爲weak

問題是assetManager.findAllMetals()的範圍。如果沒有任何東西提到它返回的資產,它們將被銷燬。由於您有一個事務數組的引用,因此它們引用的資產將在第一個循環後被銷燬。

最簡單的解決方法是讓自己的引用超出第一個循環的範圍。沿線:

let allMetails = assetManager.findAllMetals() 
var txs = [TransactionDTO]() 
for asset in allMetals { 
    for tx in asset.transactions { 
     txs.append(tx) 
     print("the asset name for this is \(tx.asset.name)") 
    } 
} 

for tx in txs { 
    print("the asset name for this is \(tx.asset.name)") 
} 
+0

當我使用弱,我在第二個打印行得到EXC_BAD_INSTRUCTION(code = EXC_i386_INVOP)。所以是的,它正在成爲零。我只是想避免內存泄漏。我只想訪問資產中的數據,但我不明白爲什麼它的可用性狀態會在2次循環迭代中發生變化。 – Brian

+1

在第一個循環中,您有一個對'asset'的引用,它在循環結束時超出了範圍,因此'asset'被釋放並且不再存在於第二個循環中。當存在循環引用時(A持有對B的引用並且B持有對A的引用),只需要擔心內存泄漏,在這種情況下,通常應該使用'weak'。在你的情況下,假設'asset'沒有引用'Transaction',那麼你也不需要。 – Michael

+0

它是一個多對一的關係。 AssetDTO有許多交易,而TransactionDTO有一個AssetDTO。那就是我有循環參考的地方。如果AssetDTO有一個數組,我想這應該是帶有引用的數組,而不是資產。 – Brian