I'm developing an application in Swift 2 (Xcode 7 beta 3) and I'm trying to use value types (structs and enums) where possible. According to Apple's documentation about memory management, working with value types should not cause any retain cycles and it should just work.
But today I encountered a huge amount of memory leaks in event handling code. I tracked it down and reduced the problem to the following minimal example.
Let's say there is a protocol Item
which defines a single property value
:
protocol Item {
var value: String { get }
}
We then create a concrete struct which implements the Item
protocol and adds an additional property additionalValue
. Let's call the struct FooItem
.
struct FooItem<T>: Item {
let value: String
let additionalValue: T
init(value: String, additionalValue: T) {
self.value = value
self.additionalValue = additionalValue
}
}
The third piece of the puzzle is another struct which wraps an item implementing the Item
protocol. It's called ItemWrapper
.
struct ItemWrapper {
let item: Item
init(item: Item) {
self.item = item
}
}
If profiled in Instruments using the Memory Leaks configuration, a memory leak appears every time an ItemWrapper
value is created with a FooItem
.
let item = FooItem(value: "protocol value", additionalValue: "foo item value")
let _ = ItemWrapper(item: item)
Here is the example Xcode project and the Instruments file: https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0
The whole code example can be viewed in this Gist: https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a
Here is the bug report: rdar://21375421
Is it a bug in the Swift compiler or am I doing anything wrong?
EDIT 1: As suggested in the comments, I reposted this question on the Apple Dev Forum in order to draw more attention from the Swift community and potentially from the developers of the language. Due to a migration of the dev forums during WWDC 2015 I had to post an updated question on the new forums. Here is the link: https://forums.developer.apple.com/message/9643
EDIT 2: The problem I originally posted in the example code seems to be resolved in Swift 2.0. Since it didn't solve the issues in my app I made another modification to the example code. Now the FooItem
's additional property has a generic type and FooItem
is annotated with the type and thus a generic type. This is how I'm using it in my app and it still causes a memory leak, but this time when the ItemWrapper
is initialized rather than when accessing the property.
EDIT 3: Fully updated the question to the modified problem which persists in Swift 2.0 and uploaded new example Xcode project.
A memory leak occurs when allocated memory becomes unreachable and the app can't deallocate it. Allowing an allocated-memory pointer to go out of scope without freeing the memory can cause a memory leak. A retain cycle in your app's object graph can also cause a memory leak.
Although I haven't got a response from Apple neither on the dev forums nor in the bug tracker and I haven't found anything related to this issue in the release notes of the latest beta versions, it seems to be solved in the Swift compiler in Xcode 7 beta 5. (Maybe it also works in beta 4. The last version I've checked was beta 3.)
The demo project doesn't produce the memory leak anymore. The same is true for my app. Yay!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With