В моем текущем проекте несколько контроллеров представления (например, vc
) порождают объекты NSOperation (например, operation
), которые выполняются в статическом NSOperationQueue. Пока операция ожидает или выполняется, она сообщит контроллеру представления через делегирование (operation.delegate = vc
, назначено, не сохранено).
Однако эти операции могут занять некоторое время, и в то же время приложение может освободить контроллер представления (извлекая их из стека контроллера навигации).
Пока все намеренно. Класс, содержащий статическое NSOperationQueue, имеет способ вернуться к операциям, поэтому контроллеры представления не сохраняют их. Они просто выделяются / инициализируются / автоматически выпускаются и помещаются в очередь.
Теперь это также вызывает проблему. После освобождения контроллера представления любые вызовы активному делегату NSOperation приведет к неправильному нарушению доступа. Из того, что я понимаю, невозможно проверить, был ли освобожден объект в указателе , как указано в этом вопросе .
Единственное исправление, о котором я могу подумать, - это сохранить операцию и установить для operation.delegate значение nil на dealloc. Но это было бы мое наименее популярное исправление, поскольку в нем было бы много дополнительных свойств / ivars, которые нужно отслеживать.
Поэтому у меня вопрос: есть ли другие способы обойти эту проблему, и если да, не могли бы вы набросать один здесь?
Приветствия
EP.
РЕШЕНИЕ : Подход, который сработал лучше всего для меня, немного отличался от ответа Гильяно:
Реализация каждого протокола делегата в администраторе очередей невозможна (более 20 различных протоколов и более 50 методов), поэтому я сохранил прямые назначения делегатов. Что я сделал, так это изменил класс, делающий вызов присваивания. Раньше это был класс (и делегат), который создал запрос, но теперь он выгружается в администратор очередей.
Администратор очередей, рядом с назначением делегата для операции, также содержит вторичный изменяемый словарь для отслеживания пар делегат / операция.
Каждый экземпляр делегата вызывает метод [QueueManager invalidateDelegate:self]
для освобождения, который затем ищет запрос, принадлежащий делегату, и обнуляет его. Пара словарь операция / делегат затем также удаляется, чтобы обеспечить правильное освобождение операции.
Наконец, когда KVO наблюдает за свойством isFinished
каждой операции, изменяемый диктет сохраняется чистым, чтобы гарантировать, что все операции сохраняют количество, фактически освобождающееся после их завершения.
Спасибо Гильяно за подсказку по использованию KVO для взлома этого!