10

Ist es möglich zu stoppen CATiledLayer zu zeichnen (drawLayer: inContext)? Es zeichnet asynchron und wenn ich versuche, CGPDFDocumentRef zu veröffentlichen, die von CATiledLayer verwendet wird, stürzt die App (EXC_BAD_ACCESS) ab.Zeichnung von CATiledLayer stoppen

Das ist meine Ansicht:

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

Und das ist, wo ich versuche, PDF zu stoppen und lassen Sie in View-Controller: v ist Instanz von TiledPDFView

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

} 
+0

Bitte bearbeiten Sie Ihre Frage, um das Absturzprotokoll für den Absturz einzuschließen. –

Antwort

9

Dieser Beitrag half mir, meine eigenen Probleme mit CATiledLayer zu lösen. Ich habe TiledPDFview.m aus der Dokumentation von Apple als Beispiel verwendet. Da ich die gesamte Ansicht und alle Kacheln irgendwann neu zeichnen muss, verwende ich einen CATiledLayer als Eigenschaft. Beim Beenden und Freigeben des Viewcontrollers stürzte es mit [CATiledLayer retain] ab: Nachricht, die an die Deallocated-Instanz gesendet wurde. Hier ist meine dealloc Methode des View-Controllers:

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

Das funktioniert für mich. Hoffe es hilft jemandem.

+0

über viele Antworten, löste ich das Problem. Diese Antwort ist die beste, die die Lösung für mich beschreibt. – negersiu

+0

Wenn die Eigenschaft mit retain gekennzeichnet ist, ist es nicht verwunderlich, dass [self.tiledLayer release], self.tiledLayer = nil; 'crashed: Diese Zeile würde das Objekt zu stark freigeben. Jetzt ist es nur durchsickern ... – DarkDust

3

die CATiledLayer von seinem Superlayer entfernen vor Freigabe der CGPDFDocumentRef.

[yourTiledLayer removeFromSuperlayer]; 

Vergessen Sie nicht, seinen Delegierten auf Null zu setzen.

yourTiledLayer.delegate = nil; 

Danach können Sie Ihre CGPDFDocumentRef sicher freigeben.

bearbeiten nach OP-Code ergänzt:

Hast du PDFPAGE mit CGPDFDocumentGetPage()? Wenn ja, sollten Sie es nicht freigeben, es ist ein automatisch freigegebenes Objekt.

Wie Sie es als Sublayer hinzufügen: Sie brauchen TiledPDFView nicht wirklich. In Ihren View-Controller, können Sie einfach tun:

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

Dann bewegen Sie Ihren drawLayer: InContext: Implementierung in Ihren View-Controller.

dann in der Ansicht Controller dealloc, lassen Sie es als:

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

Beachten Sie, dass dies nicht auf einer UIView-Unterklasse tun, als drawLayer: InContext: wird mit der Hauptschicht des UIView in Konflikt geraten.

+0

hilft immer noch nicht. Auf meiner Sicht (die CATiledLayer verwendet) habe ich eine Methode - (void) stopDrawing { [tiledLayer removeFromSuperlayer]; tiledLayer.delegate = null; } Ich rufe diese Methode, dann Release CGPDFDocumentRef ... – negersiu

+0

Wann rufst du -stopDrawing? Ich nahm an, dass Sie die CGPDFDocumentRef in -dealloc freigegeben haben. Ist CATiledLayer der Hauptlayer Ihrer Ansicht oder nur ein Sublayer? Meine Lösung wird nur mit dem CATiledLayer als Sublayer und nicht als Hauptlayer getestet. Ich empfehle Ihnen, CATiledLayer einfach als Sublayer hinzuzufügen, nicht als Ersatz für den Hauptlayer der Ansicht. – Altealice

+0

Wenn das immer noch nicht hilft, stört es Sie, Ihrem Beitrag mehr Code hinzuzufügen, um zu helfen? Wie, wo Sie den CGPDFDocumentRef initiieren, wo und wie Sie Ihren CATiledLayer hinzufügen, Ihre -drawLayer: inContext :, und wo Sie Ihre CGPDFDocumentRef freigeben. – Altealice

0

Es sieht so aus, als ob Sie dasselbe machen wie ich, das den ZoomingPDFView-Code entlehnt und in Ihr Projekt integriert. Wenn Ihre UIScrollView-Delegatmethoden in PDFScrollView unverändert sind, können Sie Ihr Problem lösen, indem Sie einfach beide Zeilen Ihrer dealloc-Methode (in TiledPDFView) kommentieren. Dieses Zeug sollte nur geschehen, wenn du die Elternansicht sowieso tötest.

1

Ich hatte ein ähnliches Problem. Ich landete einen Schwimmer Variable „Zoom“ in meinem TiledPDFView Einstellung, die ich als zoomScale von PDFScrollView im UIScrollView Delegate Methode gesetzt: scrollViewDidZoom

Da ist in meinem drawLayer Methode innerhalb TiledPDFView Ich rief nur den Inhalt dieser Methode, wenn die Float-Variable "Zoom" war über 2. Dies behebt alle Probleme von jemandem, der die Ansicht verlässt, ohne zu zoomen. Es ist möglicherweise nicht ideal für Ihren Fall, da dieser Fehler immer noch auftritt, wenn jemand über 2 zoomt und dann den viewcontroller schnell freigibt, aber Sie könnten möglicherweise eine ähnliche Technik finden, um alle Basen abzudecken.

3

object.layer.contents = Nil

Dies sollte der Thread warten zu beenden. Es hat mir geholfen.

+1

Arbeitete auch für mich. Vielen Dank. – pt2ph8

3

TiledPDFView * pdfView;

In dealloc der SuperView-Klasse von pdfView, schreiben Sie unter Zeile von Codes.

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

Das funktioniert für mich. Hoffe es wird helfen.