Я разрабатываю приложение в 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
}
}
При профилировании в «Инструментах» с использованием конфигурации «Утечки памяти» утечка памяти возникает каждый раз, когда значение ItemWrapper
создается с помощью FooItem
.
let item = FooItem(value: "protocol value", additionalValue: "foo item value")
let _ = ItemWrapper(item: item)
Вот пример проекта Xcode и файл инструментов: https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0
Пример всего кода можно просмотреть в этом Gist: https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a
Вот отчет об ошибке: rdar://21375421
Это ошибка компилятора Swift или я что-то не так делаю?
РЕДАКТИРОВАТЬ 1. Как было предложено в комментариях, я повторно разместил этот вопрос на Форуме разработчиков Apple, чтобы привлечь больше внимания сообщества Swift и, возможно, разработчиков языка. . Из-за миграции форумов разработчиков во время WWDC 2015 мне пришлось опубликовать обновленный вопрос на новых форумах. Вот ссылка: https://forums.developer.apple.com/message/9643 а>
РЕДАКТИРОВАНИЕ 2: проблема, которую я первоначально описал в примере кода, похоже, решена в Swift 2.0. Поскольку это не решило проблемы в моем приложении, я внес еще одну модификацию в код примера. Теперь дополнительное свойство FooItem
имеет универсальный тип, а FooItem
аннотируется типом и, следовательно, универсальным типом. Вот как я использую его в своем приложении, и он по-прежнему вызывает утечку памяти, но на этот раз при инициализации ItemWrapper
, а не при доступе к свойству.
РЕДАКТИРОВАТЬ 3: Полностью обновлен вопрос для измененной проблемы, которая сохраняется в Swift 2.0, и загружен новый пример проекта Xcode.