2016-10-04 34 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