CATiledLayer drawInContext вызывается после того, как исчезло связанное представление - PullRequest
4 голосов
/ 27 октября 2010

Сегодня я столкнулся с интересной проблемой iOS, связанной с CATiledLayer. Это происходит только на устройстве, а не на симуляторе.

Мое представление рисует в своем CALayer с помощью обратного вызова делегата drawLayer: inContext:. Этот слой имеет производный от CATiledLayer подслой, который выполняет собственный рисунок в переопределенном drawInContext: метод.

Оба слоя визуализируют содержимое PDF через CGContextDrawPDFPage (). (CALayer рисует версию с низким разрешением, в то время как подслой CATiledLayer рисует контент с высоким разрешением поверх.)

Я столкнулся со сценарием, в котором мне нужно было бы закончить представление - удалить его из суперпредставления и выпустить. dealloc () вызывается в представлении. Некоторое время спустя, системный метод вызывал drawInContext: метод CATiledLayer (в фоновом потоке). Он будет рисовать, но при возврате из метода Springboard будет аварийно завершать работу, и при этом также будет закрываться мое приложение.

Я исправил это, установив флаг в CATiledLayer, сказав, чтобы он больше не рендерился из метода dealloc представления.

Но я могу только представить, что есть более элегантный способ. Почему же CATiledLayer drawInContext: метод по-прежнему вызывался после родительского уровня, а представление родительского уровня было освобождено? Как правильно закрыть представление, чтобы этого не произошло?

Ответы [ 4 ]

9 голосов
/ 12 августа 2011

Медленный, но лучший способ исправить это также установить view.layer.contents = nil. Это ждет окончания потоков.

3 голосов
/ 09 февраля 2011

Установите view.layer.delegate на ноль, прежде чем снимать вид.

0 голосов
/ 10 мая 2013

Потратил довольно много времени на это.Мой последний подход состоит в том, чтобы объявить блочную переменную и присвоить себя в методе viewWillDisappear.Затем вызовите вызов setContents в глобальную очередь отправки - нет необходимости блокировать основной поток.Затем, когда setContents возвращает, снова вызовите основной поток и установите для переменной блока значение nil, что должно обеспечить освобождение контроллера представления в основном потоке.Тем не менее, я обнаружил, что разумно использовать dispatch_after для вызова основного потока, поскольку глобальная очередь отправки сохраняет контроллер представления до тех пор, пока он не выйдет из своего блока, что означает, что вы можете иметь условие состязания между его выходом (контроллер представления) и блок основного потока, устанавливающий переменную блока равной nil), что может привести к освобождению в потоке очереди глобальной отправки.

0 голосов
/ 31 марта 2011
-(void)drawLayer:(CALayer *)calayer inContext:(CGContextRef)context {    
   if(!self.superview)
      return;
   ...

ОБНОВЛЕНИЕ: Насколько я помню, в старых версиях iOS возникали проблемы с этим, когда дело дошло до CATiledLayers, но теперь для этого нужно установить для делегата значение nil, прежде чем dealloc. Смотри: https://stackoverflow.com/a/4943231/2882

...