Caída de CATiledLayer iOS

Tengo una aplicación de lector de pdf para el iPad donde estoy usando una vista de desplazamiento para mostrar cada página. Mantengo la página en vista y una página a cada lado de la página en vista. Tengo vistas separadas para vistas de paisajes y paisajes. La vista de retrato se muestra en una sola página y el visor de paisajes muestra 2 páginas.

Cuando el iPad cambia de orientación, descargo la vista para la orientación anterior y carga la vista para la nueva orientación. Entonces diga que estaba en la vista vertical y luego cambia a horizontal, la aplicación descarga la vista vertical y carga la vista horizontal. Todo esto funciona muy bien, excepto cuando los pdf son grandes.

Los PDF se dibujan usando tiledlayers. La aplicación rastrea cuando se cambia la orientación con files PDF grandes. La aplicación solo se bloquea si la orientación se cambia antes de que los mosaicos hayan sido dibujados. Mi conjetura es que está fallando porque está tratando de dibujar mosaicos en una vista de la que se ha descargado. Entonces, ¿hay una manera de detener el dibujo de mosaicos cuando descargo la vista?

Debe configurar el delegado de CALayer en nil, y luego eliminarlo de la supervisión. Esto detiene la representación, luego puede desfragmentar con security.

- (void)stopTiledRenderingAndRemoveFromSuperlayer; { ((CATiledLayer *)[self layer]).delegate = nil; [self removeFromSuperview]; [self.layer removeFromSuperlayer]; } 

Además, asegúrese de llamar a esto desde el hilo principal, o de lo contrario le esperan horribles errores.

No he mirado el desassembly para ver, pero estamos usando una solución ligeramente diferente. Establecer la propiedad CATiledLayer.content en nil bloques y obliga a que todos los bloques renderizados en queue se completen. Eso puede UIView security en un hilo de background, luego, al soltar la UIView se puede retroceder al hilo principal para permitir que la vista y la capa sean desaprovechados.

Aquí hay un ejemplo de implementación de UIViewController dealloc que mantendrá viva su vista propietaria de CATiledLayer time suficiente para detener de forma segura el procesamiento, sin bloquear el hilo principal.

 - (void)dealloc { // This works around a bug where the CATiledLayer background drawing // delegate may still have dispatched blocks awaiting rendering after // the view hierarchy is dead, causing a message to a zombie object. // We'll hold on to tiledView, flush the dispatch queue, // then let go of fastViewer. MyTiledView *tiledView = self.tiledView; if(tiledView) { dispatch_background(^{ // This blocks while CATiledLayer flushes out its queued render blocks. tiledView.layer.contents = nil; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // Make sure tiledView survives until now. tiledView.layer.delegate = nil; }); }); } } 

Esta es una suposition , pero algunos de los frameworks / classs de Apple (StoreKit, CATiledLayer, UIGestureRecognizer) afirman tener implementaciones de @property (weak) id delegate pero claramente no manejan adecuadamente al delegado weak . En cuanto a un desassembly y están decididamente decididos a competir if != nil comtesting y luego toca la propiedad débil directamente. La forma correcta es declarar un __strong Type *delegate = self.delegate , que tendrá éxito y te dará una fuerte reference garantizada para sobrevivir, o será nil , pero ciertamente no te dará una reference a un object zombie (mi Supongo que el código marco no se ha actualizado a ARC).

Bajo el capó, CATiledLayer crea una queue de despacho para hacer la representación en segundo plano y parece tocar la propiedad de delegado de manera insegura o obtiene una reference local pero sin hacerla fuerte. De cualquier manera, los bloques de procesamiento enviados enviarán felizmente un object zombie si el delegado es desasignado. Simplemente borrar el delegado no es suficiente; networkingucirá la cantidad de fallas pero no las eliminará con security.

Configurando el content = nil hace un dispatch_wait y bloquea hasta que todos los bloques de render en queue existentes hayan terminado. Regresamos al hilo principal para asegurarnos de que el dealloc está a salvo.

Si alguien tiene sugerencias de mejora por favor avíseme.