Утечка памяти в Swift структурах-как это исправить?

я разрабатываю приложение в 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) 

Instruments screenshot 1Instruments screenshot 2

вот пример проект Xcode и инструменты: https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0

на весь код например можно посмотреть в этом суть: 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.

2 ответов


хотя я не получил ответа от Apple ни на форумах разработчиков, ни в трекере ошибок, и я не нашел ничего, связанного с этой проблемой в примечаниях к выпуску последних бета-версий, он, похоже, решается в компиляторе Swift в Xcode 7 beta 5. (Возможно, он также работает в бета-4. Последняя версия, которую я проверил, была beta 3.)

демонстрационный проект больше не производит утечку памяти. То же самое верно для моего приложения. Ура!

enter image description here


Ну, вот обходной путь, хотя я понятия не имею, почему он работает. Я заметил, что если вы это сделаете:

    let theItem = itemWrapper.item
    let value = theItem.value

...вместо этого:

    let value = itemWrapper.item.value

...он не генерирует утечку памяти.