10

Czy można zatrzymać rysowanie (drawLayer: inContext) za pomocą CATiledLayer? Rysuje asynchronicznie i gdy próbuję zwolnić CGPDFDocumentRef, który jest używany przez CATiledLayer, aplikacja ulega awarii (EXC_BAD_ACCESS).Zatrzymaj rysowanie CATiledLayer

To mój widok:

@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]; 
} 

I to właśnie staram się zatrzymać i zwolnić PDF w widoku kontrolera: v jest instancją TiledPDFView

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

} 
+0

Edytuj pytanie, dołączając dziennik awarii awarii. –

Odpowiedz

9

ten post pomógł mi rozwiązać moje problemy z CATiledLayer. Użyłem TiledPDFview.m z dokumentacji Apple jako przykład. Ponieważ muszę przerysować cały widok i wszystkie kafelki w pewnym momencie, używam obiektu CATiledLayer jako własności. Podczas zamykania i deallocating viewcontroller, rozbił się z [CATainingLayer zachowaj]: Wiadomość wysłana do deallocated wystąpienie. Oto moja metoda dealloc kontrolera widoku:

- (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]; 
} 

który pracuje dla mnie. Mam nadzieję, że to komuś pomaga.

+0

przez wiele odpowiedzi, rozwiązałem problem. Ta odpowiedź jest najlepsza, która opisuje rozwiązanie dla mnie. – negersiu

+0

Jeśli własność jest oznaczona jako "zachowaj", nie byłoby to dziwne "[self.tiledLayer release], self.tiledLayer = nil;' crashed: ta linia zbyt mocno zwalnia obiekt. Teraz po prostu wyciekło ... – DarkDust

3

Zdjąć CATiledLayer z jego superlayer przed zwalnianie CGPDFDocumentRef.

[yourTiledLayer removeFromSuperlayer]; 

Nie zapomnij ustawić delegata na zero.

yourTiledLayer.delegate = nil; 

Po tym można bezpiecznie zwolnić swój CGPDFDocumentRef.

Edit po OP dodaje kod:

Dostałeś pdfPage użyciu CGPDFDocumentGetPage()? Jeśli tak, nie powinieneś go wypuszczać, jest to obiekt autoreleased.

Odnośnie sposobu dodania go jako warstwy podrzędnej: W rzeczywistości nie potrzebujesz TiledPDFView. W kontrolerze widoku można to zrobić po prostu:

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]; 

Następnie przenieś implementację drawLayer: inContext: do kontrolera widoku.

Następnie w dealloc Pana zdaniem regulatora, zwolnić ją jako:

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

pamiętać, że nie można tego zrobić na podklasy UIView, jak drawLayer: InContext: będzie kolidować z głównej warstwie UIView za.

+0

Nadal nie pomaga. W moim widoku (który używa CATiledLayer) mam metodę - (void) stopDrawing { [tiledLayer removeFromSuperlayer]; tiledLayer.delegate = nil; } Wywołanie tej metody, a następnie zwolnienie CGPDFDocumentRef ... – negersiu

+0

Kiedy wywołujesz -stopDrawing? Zakładałem, że zwalniasz CGPDFDocumentRef w -dealloc. Czy warstwa główna widoku CATiledLayer to twój widok, czy tylko podwarstwa? Moje rozwiązanie jest testowane tylko z CATiledLayer jako podwarstwa, a nie jako warstwa główna. Polecam tylko dodać CATiledLayer jako podwarstwę, a nie jako zamiennik głównej warstwy widoku. – Altealice

+0

Jeśli to nadal nie pomoże, czy chcesz dodać więcej kodu do swojego posta, aby pomóc? Tak jak przy inicjowaniu CGPDFDocumentRef, gdzie i jak dodajesz CATiledLayer, twój -drawLayer: inContext :, i gdzie wypuszczasz swój CGPDFDocumentRef. – Altealice

0

Wygląda na to, że robisz to samo, co ja, pożyczając kod ZoomingPDFView i integrując go z projektem. Jeśli metody delegatów UIScrollView w PDFScrollView pozostaną niezmienione, możesz rozwiązać problem, komentując oba wiersze metody dealloc (w TiledPDFView). Te rzeczy powinny się zdarzyć tylko wtedy, gdy zabijesz widok rodzica.

1

Miałem podobny problem. skończyło się ustawienie zmiennej typu float „Zoom” w moim TiledPDFView którą ustawiony jako zoomScale z PDFScrollView w metodzie UIScrollView Delegat: scrollViewDidZoom

Wtedy w moim sposobie drawLayer wewnątrz TiledPDFView ja tylko nazywa zawartość tej metody, jeśli zmienna zmienna "powiększenie" była powyżej 2. Rozwiązuje to problemy osób opuszczających widok bez powiększania. To może nie być idealne dla twojej sprawy, ponieważ ten błąd nadal występuje, jeśli ktoś powiększy się powyżej 2, a następnie zwolni kontroler viewcontroller szybko, ale możesz znaleźć podobną technikę, aby pokryć wszystkie bazy.

3

object.layer.contents = zero

powinno czekać na gwint do końca. Pomogło mi to w moim przypadku.

+1

Pracował także dla mnie. Dzięki. – pt2ph8

3

KafelkiPDFView * pdfView;

W dealloc z klasy superview pdfView, napisz poniżej linię kodów.

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

To działa dla mnie. Mam nadzieję, że to pomoże.