Остановить рисование CATiledLayer - PullRequest
10 голосов
/ 06 октября 2010

Можно ли остановить CATiledLayer рисовать (drawLayer: inContext)? Он рисует асинхронно, и когда я пытаюсь освободить CGPDFDocumentRef, который используется CATiledLayer, приложение падает (EXC_BAD_ACCESS).

Это мой взгляд:

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

И здесь я пытаюсь остановить и выпустить PDF в виде контроллера: v является экземпляром TiledPDFView

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

 }

Ответы [ 6 ]

9 голосов
/ 23 ноября 2010

этот пост помог мне решить мою собственную проблему с CATiledLayer. Я использовал TiledPDFview.m из документации Apple в качестве примера. Поскольку в какой-то момент мне нужно перерисовать весь вид и все плитки, я использую CATiledLayer в качестве свойства. При выходе и освобождении viewcontroller он вылетал с [CATiledLayer retain]: сообщение отправлено на освобожденный экземпляр Вот мой метод dealloc контроллера представления:

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

Это работает для меня. Надеюсь, это кому-нибудь поможет.

3 голосов
/ 08 июля 2016

TiledPDFView * pdfView;

В dealloc класса superview pdfView напишите строку с кодами ниже.

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

Это работает для меня. Надеюсь, это поможет.

3 голосов
/ 17 ноября 2010

object.layer.contents = Nil

Это должно дождаться окончания потока. Это помогло в моем случае.

3 голосов
/ 06 октября 2010

Удалите CATiledLayer из его суперслоя перед выпуском CGPDFDocumentRef.

[yourTiledLayer removeFromSuperlayer];

Не забудьте также установить его делегат на ноль.

yourTiledLayer.delegate = nil;

После этого вы можете безопасно выпуститьCGPDFDocumentRef.

Редактировать после того, как OP добавляет код:

Получили ли вы pdfPage, используя CGPDFDocumentGetPage()?Если это так, вы не должны выпускать его, это объект с автоматическим освобождением.

Относительно того, как добавить его в качестве подслоя: вам на самом деле не нужен TiledPDFView.В вашем контроллере представления вы можете просто сделать это:

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

Затем переместите реализацию drawLayer: inContext: в ваш контроллер представления.

Затем в вызове контроллера вашего представления освободите его как:

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

Обратите внимание, что вы не можете сделать это на подклассе UIView, поскольку drawLayer: inContext: будет конфликтовать с основным слоем UIView.

1 голос
/ 13 ноября 2010

У меня была похожая проблема. Я закончил тем, что установил переменную float "zoom" в моем TiledPDFView, который я установил в качестве zoomScale PDFScrollView в методе делегата UIScrollview: scrollViewDidZoom

Тогда в моем методе drawLayer внутри TiledPDFView я вызывал содержимое этого метода только в том случае, если переменная типа float "zoom" была выше 2. Это исправляет любые проблемы, когда кто-то покидает вид без увеличения. Это может не быть идеальным для вашего случая, так как эта ошибка все еще происходит, если кто-то увеличивает масштаб выше 2, затем быстро выпускает viewcontroller, но вы могли бы найти подобную технику для всех баз.

0 голосов
/ 08 октября 2010

Похоже, вы делаете то же самое, что и я, заимствуя код ZoomingPDFView и интегрируя его в свой проект. Если ваши методы делегата UIScrollView в PDFScrollView не изменились, вы можете решить вашу проблему, просто комментируя обе строки вашего метода dealloc (в TiledPDFView). В любом случае, такое должно происходить только тогда, когда вы убиваете родительское представление.

...