10

È possibile interrompere CATiledLayer per disegnare (drawLayer: inContext)? Disegna in modo asincrono e quando provo a rilasciare CGPDFDocumentRef, che viene utilizzato da CATiledLayer, l'app si arresta in modo anomalo (EXC_BAD_ACCESS).Interruzione del disegno di CATiledLayer

Questo è mio punto di vista:

@implementation TiledPDFView 

- (id)initWithFrame:(CGRect)frame andScale:(CGFloat)scale{ 
    if ((self = [super initWithFrame:frame])) { 

     CATiledLayer *tiledLayer = (CATiledLayer *)[self layer]; 
     tiledLayer.levelsOfDetail = 4; 
     tiledLayer.levelsOfDetailBias = 4; 
     tiledLayer.tileSize = CGSizeMake(512.0, 512.0); 
     myScale = scale; 
    } 
    return self; 
} 

// Set the layer's class to be CATiledLayer. 
+ (Class)layerClass { 
    return [CATiledLayer class]; 
} 

- (void)stopDrawing{ 
    CATiledLayer *tiledLayer = (CATiledLayer *)[self layer]; 
    [tiledLayer removeFromSuperlayer]; 
    tiledLayer.delegate = nil; 
} 
// Set the CGPDFPageRef for the view. 
- (void)setPage:(CGPDFPageRef)newPage 
{ 
    CGPDFPageRelease(self->pdfPage); 
    self->pdfPage = CGPDFPageRetain(newPage); 

    //self->pdfPage = newPage; 
} 


-(void)drawRect:(CGRect)r 
{ 
} 


// Draw the CGPDFPageRef into the layer at the correct scale. 
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context 
{ 

    // First fill the background with white. 
    CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); 
    CGContextFillRect(context,self.bounds); 

    CGContextSaveGState(context); 
    // Flip the context so that the PDF page is rendered 
    // right side up. 
    CGContextTranslateCTM(context, 0.0, self.bounds.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 

    // Scale the context so that the PDF page is rendered 
    // at the correct size for the zoom level. 
    CGContextScaleCTM(context, myScale,myScale);  
    CGContextDrawPDFPage(context, pdfPage); 
    CGContextRestoreGState(context); 

} 

// Clean up. 
- (void)dealloc { 
    CGPDFPageRelease(pdfPage); 

    [super dealloc]; 
} 

Ed è qui che cerco di fermarsi e rilasciare PDF in controller di vista: v è un'istanza di TiledPDFView

-(void) stopDwaring { 
    [v stopDrawing]; 
    [v removeFromSuperview]; 
    [v release]; 
    [self.view removeFromSuperview]; 
    self.view = nil; 
    CGPDFDocumentRelease(pdf); 

} 
+0

Modifica la domanda per includere il registro degli arresti anomali in caso di arresto anomalo. –

risposta

9

questo post mi ha aiutato a risolvere il mio problema con CATiledLayer. Ho usato TiledPDFview.m dalla documentazione di Apple come esempio. Dato che a un certo punto ho bisogno di ridisegnare l'intera vista e tutte le tessere, uso un CATiledLayer come proprietà. All'uscita e deallocazione del viewcontroller, si è arrestato in modo anomalo con [CATiledLayer retain]: messaggio inviato all'istanza deallocata. Ecco il mio metodo dealloc del controller della vista:

- (void)dealloc { 
    self.tiledLayer.contents=nil; 
    self.tiledLayer.delegate=nil; 
    [self.tiledLayer removeFromSuperlayer]; 

    // note: releasing the layer still crashes- 
    // I guess removeFromSuperlayer releases it already, 
    // but couldn't find documentation so far. 
    // So that's why it's commented out: 
    // [self.tiledLayer release], self.tiledLayer=nil; 

    //release the other viewcontroller stuff... 
    [super dealloc]; 
} 

che funziona per me. Spero che aiuti qualcuno.

+0

su molte risposte, ho risolto il problema. Questa risposta è la migliore che descrive la soluzione per me. – negersiu

+0

Se la proprietà è contrassegnata come 'retain', non c'è da meravigliarsi se [self.tiledLayer release], self.tiledLayer = nil;' interrotto: quella riga sovrascriverà l'oggetto. Ora è appena trapelato ... – DarkDust

3

Rimuovere il CATiledLayer dalla sua superlayer prima Rilascio di CGPDFDocumentRef.

[yourTiledLayer removeFromSuperlayer]; 

Non dimenticare di impostare anche il delegato su zero.

yourTiledLayer.delegate = nil; 

Dopodiché, è possibile rilasciare in modo sicuro il proprio CGPDFDocumentRef.

Modifica dopo OP aggiunge il codice:

Hai avuto pdfPage utilizzando CGPDFDocumentGetPage()? Se è così, non dovresti rilasciarlo, è un oggetto autorelegato.

Informazioni su come aggiungerlo come sottolivello: In realtà non è necessario TiledPDFView. Nel vostro controller della vista, si può semplicemente fare questo:

CATiledLayer *tiledLayer = [CATiledLayer layer]; 
tiledLayer.delegate = self; //sets where tiledLayer will look for drawLayer:inContext: 
tiledLayer.tileSize = CGSizeMake(512.0f, 512.0f); 
tiledLayer.levelsOfDetail = 4; 
tiledLayer.levelsOfDetailBias = 4; 
tiledLayer.frame = CGRectIntegral(CGRectMake(0.0f, 0.0f, 512.0f, 512.0f)); 
[self.view.layer addSublayer:tiledLayer]; 

quindi spostare il drawLayer: InContext: implementazione al controller della vista.

Poi, nel dealloc del controller della vista, rilasciarlo come:

[tiledLayer removeFromSuperlayer]; 
tiledLayer.delegate = nil; 
CGPDFDocumentRelease(pdf); 

Notare che non è possibile farlo su una sottoclasse UIView, come il drawLayer: InContext: in conflitto con strato principale del UIView.

+0

Ancora non aiuta. A mio avviso (che usa CATiledLayer) ho un metodo - (void) stopDrawing { [tiledLayer removeFromSuperlayer]; tiledLayer.delegate = nil; } Chiamo questo metodo, quindi rilascio CGPDFDocumentRef ... – negersiu

+0

Quando si chiama -stopDrawing? Supponevo che stavi rilasciando il file CGPDFDocumentRef in -dealloc. Inoltre, CATiledLayer è il livello principale della tua vista o solo un sottolivello? La mia soluzione è stata testata con CATiledLayer solo come sottolivello, non come livello principale. Vi consiglio di aggiungere CATiledLayer come sottolivello, non in sostituzione del livello principale della vista. – Altealice

+0

Se non ti è ancora d'aiuto, ti dispiace aggiungere altro codice al tuo post per aiutarti? Come quando si avvia CGPDFDocumentRef, dove e come si aggiunge CATiledLayer, il tuo -drawLayer: inContext :, e dove si rilascia CGPDFDocumentRef. – Altealice

0

Sembra che tu stia facendo la stessa cosa che sono, prendendo in prestito il codice ZoomingPDFView e integrandolo nel tuo progetto. Se i metodi di delega UIScrollView in PDFScrollView sono invariati, è possibile risolvere il problema semplicemente commentando entrambe le righe del metodo dealloc (in TiledPDFView). Quella roba dovrebbe accadere solo quando uccidi comunque la vista genitore.

1

Ho avuto un problema simile. Ho finito per impostare una variabile float "zoom" nel mio TiledPDFView che ho impostato come zoomScale della PDFScrollView nel metodo UIScrollView Delegato: scrollViewDidZoom

Poi nel mio metodo drawLayer all'interno TiledPDFView ho chiamato solo il contenuto di quel metodo se il variabile variabile "zoom" era sopra 2. Questo risolve eventuali problemi di qualcuno che lascia la vista senza zoom. Potrebbe non essere l'ideale per il tuo caso in quanto questo errore si verifica ancora se qualcuno ingrandisce 2 e rilascia rapidamente il viewcontroller, ma potresti essere in grado di trovare una tecnica simile per coprire tutte le basi.

3

object.layer.contents = Nil

Questo dovrebbe attendere che il thread per finire. Ha aiutato nel mio caso.

+1

Ha funzionato anche per me. Grazie. – pt2ph8

3

TiledPDFView * pdfView;

Nel dealloc della classe superview pdfView, scrivere sotto la riga di codici.

- (void)dealloc { 
     if (nil != self.pdfView.superview) { 
      self.pdfView.layer.delegate = nil; 
      [self.pdfView removeFromSuperview]; 
     } 
} 

Questo funziona per me. Spero che ti sarà d'aiuto.

Problemi correlati