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