Swift 结构中的内存泄漏 - 如何解决这个问题?
Memory leak in Swift structures - How to fix this?
我正在 Swift 2 (Xcode 7 beta 3) 中开发一个应用程序,我正在尝试尽可能使用值类型(结构和枚举)。根据 Apple 关于内存管理的文档,使用值类型不应导致任何保留周期,它应该可以正常工作。
但是今天我在事件处理代码中遇到了大量的内存泄漏。我追踪到它并将问题简化为以下最小示例。
假设有一个协议 Item
定义了单个 属性 value
:
protocol Item {
var value: String { get }
}
然后我们创建一个具体的结构来实现 Item
协议并添加一个额外的 属性 additionalValue
。让我们调用结构 FooItem
.
struct FooItem<T>: Item {
let value: String
let additionalValue: T
init(value: String, additionalValue: T) {
self.value = value
self.additionalValue = additionalValue
}
}
拼图的第三部分是另一个结构,它包装了一个实现 Item
协议的项目。它被称为 ItemWrapper
.
struct ItemWrapper {
let item: Item
init(item: Item) {
self.item = item
}
}
如果使用内存泄漏配置在 Instruments 中进行分析,每次使用 FooItem
创建 ItemWrapper
值时都会出现内存泄漏。
let item = FooItem(value: "protocol value", additionalValue: "foo item value")
let _ = ItemWrapper(item: item)
这里是示例 Xcode 项目 和 Instruments 文件:https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0
整个代码示例可以在这个要点中查看:https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a
错误报告如下:rdar://21375421
这是 Swift 编译器中的错误还是我做错了什么?
编辑 1:正如评论中所建议的,我在 Apple Dev Forum 中重新post编辑了这个问题为了引起 Swift 社区和语言开发人员的更多关注。由于 WWDC 2015 期间开发论坛的迁移,我不得不 post 在新论坛上更新问题。这是link:https://forums.developer.apple.com/message/9643
编辑 2:我最初在示例代码中 post 编辑的问题似乎在 Swift 2.0。由于它没有解决我的应用程序中的问题,我对示例代码进行了另一次修改。现在 FooItem
的附加 属性 有一个通用类型,并且 FooItem
被注释了类型,因此是一个通用类型。这就是我在我的应用程序中使用它的方式,它仍然会导致内存泄漏,但这次 ItemWrapper
被初始化而不是访问 属性.
编辑 3:将问题完全更新为 Swift 2.0 中仍然存在的修改后的问题,并上传了新示例 Xcode 项目。
好吧,这里有一个解决方法,虽然我不知道它为什么有效。我注意到如果你这样做:
let theItem = itemWrapper.item
let value = theItem.value
...而不是这个:
let value = itemWrapper.item.value
...它不会产生内存泄漏。
尽管我在开发论坛和错误跟踪器中都没有收到 Apple 的回复,而且我在最新测试版的发行说明中也没有找到与此问题相关的任何内容,但似乎是在 Xcode 7 beta 5 中的 Swift 编译器中解决。 (也许它也适用于 beta 4。我检查的最后一个版本是 beta 3。)
演示项目不再产生内存泄漏。我的应用程序也是如此。耶!
我正在 Swift 2 (Xcode 7 beta 3) 中开发一个应用程序,我正在尝试尽可能使用值类型(结构和枚举)。根据 Apple 关于内存管理的文档,使用值类型不应导致任何保留周期,它应该可以正常工作。
但是今天我在事件处理代码中遇到了大量的内存泄漏。我追踪到它并将问题简化为以下最小示例。
假设有一个协议 Item
定义了单个 属性 value
:
protocol Item {
var value: String { get }
}
然后我们创建一个具体的结构来实现 Item
协议并添加一个额外的 属性 additionalValue
。让我们调用结构 FooItem
.
struct FooItem<T>: Item {
let value: String
let additionalValue: T
init(value: String, additionalValue: T) {
self.value = value
self.additionalValue = additionalValue
}
}
拼图的第三部分是另一个结构,它包装了一个实现 Item
协议的项目。它被称为 ItemWrapper
.
struct ItemWrapper {
let item: Item
init(item: Item) {
self.item = item
}
}
如果使用内存泄漏配置在 Instruments 中进行分析,每次使用 FooItem
创建 ItemWrapper
值时都会出现内存泄漏。
let item = FooItem(value: "protocol value", additionalValue: "foo item value")
let _ = ItemWrapper(item: item)
这里是示例 Xcode 项目 和 Instruments 文件:https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0
整个代码示例可以在这个要点中查看:https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a
错误报告如下:rdar://21375421
这是 Swift 编译器中的错误还是我做错了什么?
编辑 1:正如评论中所建议的,我在 Apple Dev Forum 中重新post编辑了这个问题为了引起 Swift 社区和语言开发人员的更多关注。由于 WWDC 2015 期间开发论坛的迁移,我不得不 post 在新论坛上更新问题。这是link:https://forums.developer.apple.com/message/9643
编辑 2:我最初在示例代码中 post 编辑的问题似乎在 Swift 2.0。由于它没有解决我的应用程序中的问题,我对示例代码进行了另一次修改。现在 FooItem
的附加 属性 有一个通用类型,并且 FooItem
被注释了类型,因此是一个通用类型。这就是我在我的应用程序中使用它的方式,它仍然会导致内存泄漏,但这次 ItemWrapper
被初始化而不是访问 属性.
编辑 3:将问题完全更新为 Swift 2.0 中仍然存在的修改后的问题,并上传了新示例 Xcode 项目。
好吧,这里有一个解决方法,虽然我不知道它为什么有效。我注意到如果你这样做:
let theItem = itemWrapper.item
let value = theItem.value
...而不是这个:
let value = itemWrapper.item.value
...它不会产生内存泄漏。
尽管我在开发论坛和错误跟踪器中都没有收到 Apple 的回复,而且我在最新测试版的发行说明中也没有找到与此问题相关的任何内容,但似乎是在 Xcode 7 beta 5 中的 Swift 编译器中解决。 (也许它也适用于 beta 4。我检查的最后一个版本是 beta 3。)
演示项目不再产生内存泄漏。我的应用程序也是如此。耶!