[UIViewController hash]: сообщение отправлено на освобожденный экземпляр с ARC - PullRequest
2 голосов
/ 26 марта 2012

Не удается решить эту проблему, [хеш UIViewController] отправляется в контроллер представления, который был правильно освобожден, он был помещен в навигацию, а затем извлечен, а затем в некоторый случайный момент позже это происходит. Похоже, класс UIViewController имеет некоторую статическую коллекцию контроллеров представления, где ссылка на старый контроллер все еще сохраняется, несмотря на удаление.

 206, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x0225cdee CoreFoundation`___forwarding___ + 206
    frame #1: 0x0225ccb2 CoreFoundation`_CF_forwarding_prep_0 + 50
    frame #2: 0x017e1cd1 Foundation`objectHash + 33
    frame #3: 0x017e3444 Foundation`hashProbe + 47
    frame #4: 0x017f5d03 Foundation`-[NSConcreteHashTable hashGrow] + 217
    frame #5: 0x017e3407 Foundation`-[NSConcreteHashTable addObject:] + 136
    frame #6: 0x00f98089 UIKit`+[UIViewController setViewController:forView:] + 101
    frame #7: 0x00f94c71 UIKit`-[UIViewController setView:] + 542
    frame #8: 0x017ecf30 Foundation`_NSSetUsingKeyValueSetter + 77
    frame #9: 0x017ecedb Foundation`-[NSObject(NSKeyValueCoding) setValue:forKey:] + 287
    frame #10: 0x01807d50 Foundation`-[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 393
    frame #11: 0x010ef71a UIKit`-[UIRuntimeOutletConnection connect] + 106
    frame #12: 0x022f7dea CoreFoundation`-[NSObject performSelector:] + 58
    frame #13: 0x022617f1 CoreFoundation`-[NSArray makeObjectsPerformSelector:] + 273
    frame #14: 0x010ee26e UIKit`-[UINib instantiateWithOwner:options:] + 1178
    frame #15: 0x00f941fc UIKit`-[UIViewController _loadViewFromNibNamed:bundle:] + 286
    frame #16: 0x00f94779 UIKit`-[UIViewController loadView] + 302

Похоже, что закрытый метод [UIViewController setViewController: forView:], вызываемый из [UIViewController setView:], сохраняет каждый контроллер представления в словаре уровня представления - возможно, контроллер представления. И в какой-то момент позже, при добавлении другого VC в коллекцию, он должен расти, что вызывает перефразирование всех значений в коллекции, вызывая вызов [UIViewController hash] для delloced VC. Теперь вопрос, почему ссылка VC все еще там? Может быть, потому что представление все еще живо без делегата контроллера.

ОБНОВЛЕНИЕ: Я могу подтвердить, что представление контроллера представления все еще живо после того, как VC был вытолкнут, несмотря на то, что VC был разрушен. Хотя я не совсем уверен, почему.

Ответы [ 3 ]

3 голосов
/ 26 марта 2012

Ух, хорошо выяснил, что было, что-то очень плохое (шлепает себя по запястью).

Я реорганизовал абстрактный подкласс UIViewController в категорию на UIViewController, выполнив нечто похожее на UINavigationController, где он добавляет функции, связанные с навигацией, в UIViewController.Но что я не заметил, так это то, что мой подкласс UIViewController реализовал dealloc, поэтому после преобразования в категорию он заменил метод dealloc UIViewController.

Вы думаете, что компилятор выдаст мне предупреждение за это, обычно это происходит, если вы заменяете метод на категорию, но, как кажется, не в случае dealloc (возможно, что-то связанное с генерацией кода ARC)

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

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

Кроме того, поскольку это происходит некоторое время спустя, я предполагаю, что второй контроллер представлениязапускает какой-то длительный процесс.Делегат указывает на тот же контроллер представления.

Когда вы открываете контроллер представления, длительный процесс все еще выполняется, и когда он завершается, делегат больше не указывает на правильный объект.

Но, как я уже сказал, это полное предположение, поскольку вы не опубликовали никакого кода.

0 голосов
/ 26 марта 2012

Я не уверен, почему вы думаете, что это странно.После извлечения viewController из стека его, вероятно, необходимо удалить из хеш-таблицы, прежде чем его можно будет освободить.Для этого им нужно вызвать метод хеширования.Кроме того, IOS может держать viewController некоторое время по соображениям производительности.Если это потребуется быстро снова, они просто вызовут viewWillLoad: вместо того, чтобы создавать новый контроллер представления.Суть в том, что Apple решает, что делать с viewController после его извлечения.

Это было бы странно, если бы хеш-метод viewController был вызван после его метода release.Вы это проверяли?

...