首页 > 解决方案 > 将对象存储在结构中时出现 Swift 问题

问题描述

我对这里的内存管理方式感到困惑,假设有一个场景:

import Foundation

class SomeObject {
    deinit {
        print("deinitCalled")
    }
}
struct SomeStruct {
    let object = SomeObject()
    var closure: (() -> Void)?
}

func someFunction() {
    var someStruct = SomeStruct()
    someStruct.closure = {
        print(someStruct)
    }
    someStruct.closure?()
}
someFunction()
print("the end")

我在这里期望的是:

Optional(test.SomeStruct(object: test.SomeObject, closure: Optional((Function))))
deinitCalled
the end

然而我得到的是:

SomeStruct(object: test.SomeObject, closure: Optional((Function)))
the end

如果我查看内存映射:

在此处输入图像描述

保留周期

在这种情况下如何管理内存

标签: swiftmemory-managementstruct

解决方案


首先,您应该非常非常小心地将引用类型放在值类型中,尤其是对外部世界可见的可变引用类型。结构始终是值类型,但您还希望它们具有值语义,并且在包含引用类型的同时做到这一点是具有挑战性的。(很有可能,很多 stdlib 类型都这样做是为了实现写时复制;这只是具有挑战性。)

所以简短的版本是“你几乎肯定不想做你在这里做的事情”。

但是,如果您在 SomeStruct 中维护了值语义,那么答案就是制作一个副本。复制一个值类型总是好的。

someStruct.closure = { [someStruct] in
    print(someStruct)
}

这为闭包提供了它自己的不可变值,即someStruct. 未来的更改someStruct不会影响此关闭。

如果您的意思是未来的更改会someStruct影响此闭包,那么您可能违反了值语义,您应该重新设计(可能通过使 SomeStruct 成为一个类,如果您的意思是它具有引用语义)。


推荐阅读