В моем текущем проекте несколько контроллеров представлений (например, 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 для взлома этого!