UITableView - moveRowAtIndexPath вызывает утечку памяти - PullRequest
1 голос
/ 11 марта 2012

Обзор

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

Когда происходит утечка

  • Когда вы создаете экземпляр NSIndexPath с использованием метода indexPathForRow: section: (как показано в разделе кода), а затем передаете его методу UITableView 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 (не уверен, что это хороший методвремя в среде автоматического подсчета ссылок

    1056 * CFRelease ((__ bridge void *) toIndexPath);

Вопросы:

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

Ответы [ 2 ]

1 голос
/ 09 апреля 2012

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

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

Я добавил некоторый отладочный код для регистрации retainCount NSIndexPath до и после вызова moveRowAtIndexPath: toIndexPath: и получил 1 до (этов пуле авто-релизов, так что это ожидаемо) и 5 ​​позже (определенно не ожидается, если он не был добавлен в пул авто-релизов еще 4 раза!)

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

1 голос
/ 20 марта 2012

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

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

...