2016-09-19 7 views
1

Я вижу странное поведение с инструментом распределения в Xcode 8 и Swift 2.3. У меня есть объект (A), на который вызывается deinit, все, кроме одного из объектов, которые освобождают ссылки A (это тот, который не является отдельной проблемой памяти, насколько я могу судить), но объект продолжается которые будут перечислены как «живые» и постоянные в инструменте распределения. Кроме того, когда я пытаюсь отлаживать это сохраняет все, что я вижу:Deinit Called But Object Still in Memory

enter image description here

Обратите внимание, что я подтвердил Deinit в настоящее время выполняется:

  • Добавление печати строки в метод Deinit
  • Добавление точки останова к методу Deinit
  • проверки того, что другие объекты, которые A ссылки де-распределенные, и они получают релиз (-1) порядковый счет, который утверждает, чтобы это произошло внутри в A.__deallocating_deinit метод

Однако по какой-то неизвестной причине он, похоже, стоит вокруг.

+0

Уверены ли вы, что нет другой ссылки на этот объект? Согласно ARC объект не будет освобожден до тех пор, пока счетчик ссылок не станет 0. Возможно, вы сохраняете ссылку на это представление где-то еще (в другом VC). – Janmenjaya

+1

Если deinit вызывается (и вернулся), то объект почти наверняка ушел, независимо от того, все ли ссылки на него все еще существуют. Обычно, если вы видите эту проблему, есть вторая копия объекта, которого вы не ожидали. («Есть вторая копия, которую вы не ожидали» на самом деле является причиной широкого разнообразия, казалось бы, невозможного поведения). Проверьте адреса памяти. Но еще одна вещь, которую я бы искал, - это случайное сохранение объекта в 'deinit'. Это может привести вас в беспорядок (но все же * возможно, * не вызовет такого симптома, я делаю ставку на дополнительную копию). –

+0

@RobNapier Я действительно подтвердил, что на самом деле создается только один объект. 'deinit' выполнялся и все еще не освобождал объект. Хотя я до сих пор не понимаю 100%, почему эта проблема возникла, я добавил ответ ниже, который в конечном итоге решил проблему для меня. –

ответ

1

После нескольких часов поиска мне наконец удалось (в основном) понять это.

В этом случае у меня есть класс A, который имеет 6 свойств, один из которых является экземпляром класса B. Класс A регистрирует обратные вызовы блока с классом B. Класс B принимает события извне основного цикла цикла, на отдельный NSThread, который не был надлежащим образом завернут в @autoreleasepool. В результате класс B удерживался дольше, чем предполагалось, что привело к тому, что его блоки с обратными вызовами на A сохранялись дольше, чем предполагалось.

Причина, по которой я говорю «в основном», поняла, что класс А зарегистрировал все эти блоки с [unowned self]. По еще неизвестной причине этого оказалось достаточно, чтобы позволить выполнить deinit, но недостаточно, чтобы фактически освободить объект. Обертка другой нити в @autoreleasepool позволила приложению освободить B, что было тогда достаточно, чтобы освободить A.

+0

Я собираюсь оставить этот ответ незаметным для того, чтобы узнать, может ли кто-либо на основе этого ответа определить «лучшее» решение, которое фактически решает проблему. –

 Смежные вопросы

  • Нет связанных вопросов^_^