1

ОбзорUITableView - moveRowAtIndexPath вызывает утечку памяти

  • В проекте IOS, у меня есть UITableView, и я пытаюсь переместить строку UITableView.
  • В моей модели порядок данных был изменен, так что я пытаюсь визуально показать в таблице, поэтому я использовал UITableView «s метод moveRowAtIndexPath:toIndexPath:
  • Для того, чтобы сделать так, что я создал NSIndexPath экземпляр, который я передаю методу UITableView.

Когда утечка accurs

  • При создании экземпляра NSIndexPath с помощью метода indexPathForRow: section: (как показано в секции кода), а затем передать его в методе UITableView «s moveRowAtIndexPath: toIndexPath: его утечки.

Примечание:

  • Я использую ARC (автоматический подсчет ссылок)
  • XCode 4.3.1
  • Я использовал инструменты (Xcode меню - Product> Профиль), чтобы определить утечка памяти

Код: (внутри UITableViewController)

NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:newRow inSection:0]; //leaking 

[self.tableView beginUpdates]; 
[self.tableView moveRowAtIndexPath:originalIndexPath toIndexPath:newIndexPath]; //I think this causes the leak 
[self.tableView endUpdates]; 

шаги я попытался

  • закомментировать вызов метода moveRowAtIndexPath:originalIndexPath toIndexPath:, предотвращает утечку памяти
  • я вручную используется CFRelease (не уверен, что это хорошая практика в среде автоматического подсчета ссылок)

    CFRelease ((__ bridg e void *) toIndexPath);

Вопросы:

  • Почему это происходит? есть ли какое-нибудь решение?
  • Является ли результат утечки памяти прибора точным?
  • Есть ли ошибка в методе UITableView moveRowAtIndexPath:originalIndexPath toIndexPath:?
  • Есть ли CFRelease вариант? Есть ли безопасный способ предотвратить сбой приложения в случае, если CFRelease пытается освободить уже выпущенную память (см. Точный код выше).
+0

я не уверен, если инструменты будут указывать на утечку памяти, если объект был разыменованный, но не сбор мусора, поэтому это комментарий, а не ответ. Вы пытались запустить [[NSGarbageCollector defaultInstance] collectExhaustively] после обновлений? –

+0

спасибо за ответ, я делаю проект iOS, поэтому я не смог бы попробовать сбор мусора. исправьте меня, если я ошибаюсь – user1046037

ответ

1

Код, который вы опубликовали, не должен приводить к утечке памяти в настройке ARC (равно как и без ARC, если на то пошло).

Если вы действительно подозреваете ошибку (например, что UITableView не может освободить объект NSIndexPath), возможно, вы попытаетесь вручную освободить его в качестве временного обходного пути. Однако вы уверены, что он просто не освобождает его после завершения анимации? Даже если у вас нет анимации, может быть, что объект indexPath не будет выпущен до тех пор, пока не будет достигнут простаивающий цикл (это довольно часто встречается с компонентами GUI и, очевидно, также с автореализованными объектами).

Однако, чтобы подтвердить, что это действительно утечка, попробуйте исследовать, увеличивается ли память во времени в долгосрочной перспективе (возможно, UITableView придерживается своего последнего объекта indexPath, в котором он, вероятно, не будет быть проблемой). Кроме того, попробуйте запустить отладчик с помощью набора переменных среды NSZombieEnabled. Это позволит обнаружить и прорваться в отладчик при попытке удвоить выпуск объекта.

+0

Большое спасибо за ответ, я доволен другой проблемой, я попробую NSZombieEnabled. – user1046037

1

У меня недостаточно комментариев, чтобы добавить комментарий, поэтому мне придется добавить ответ. Я также вижу эту утечку. Я НЕ использую ARC, и я не использую beginUpdates/endUpdates, чтобы обернуть один вызов moveRowAtIndexPath: toIndexPath: Instruments утверждает, что 32-байтная утечка NSIndexPath всякий раз, когда я вызываю этот метод.

Звонок в индекс NSIndexPathPathForRow: inSection: должен возвращать автоматически выпущенный объект, который не нужно вручную освобождать. Я подозреваю, что moveRowAtIndexPath: toIndexPath: неправильно удерживает объект, вызывая утечку.

Я добавил код отладки, чтобы зарегистрировать saveCount из NSIndexPath до и после вызова moveRowAtIndexPath: toIndexPath: и получил 1 раньше (он находится в пуле авто-релизов, так что ожидается) и 5 ​​после (определенно не ожидается, если он был добавлен в пул авто-релиз еще 4 раза)

Edit: Смотрите также https://devforums.apple.com/message/639904 (требуется аккаунт разработчика Apple)

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