10

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

Это мое мнение:

@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); 

} 
+0

Измените свой вопрос, включив в него аварийный журнал для сбоя. –

ответ

9

Это сообщение помогло мне решить мою собственную проблему с CATiledLayer. В качестве примера я использовал TiledPDFview.m из документации Apple. Поскольку в какой-то момент мне нужно перерисовать весь вид и все плитки, я использую свойство CATiledLayer как свойство. При выходе и освобождении диспетчера view он разбился с [CATiledLayer сохранить]: сообщение отправлено на освобожденный экземпляр. Вот мой метод 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]; 
} 

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

+0

по многим ответам, я решил проблему. Этот ответ - лучшее, что описывает решение для меня. – negersiu

+0

Если свойство помечено 'keep', было бы неудивительно' [self.tiledLayer release], self.tiledLayer = nil; 'crashed: эта строка перевыполнила бы объект. Теперь он просто просочился ... – DarkDust

3

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

[yourTiledLayer removeFromSuperlayer]; 

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

yourTiledLayer.delegate = nil; 

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

Edit после 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: осуществление в контроллер представления.

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

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

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

+0

По-прежнему не помогает. На мой взгляд (который использует CATiledLayer) у меня есть метод - (void) stopDrawing { [tiledLayer removeFromSuperlayer]; tiledLayer.delegate = nil; } Я вызываю этот метод, затем отпустите CGPDFDocumentRef ... – negersiu

+0

Когда вы вызываете -stopDrawing? Я предположил, что вы выпускаете CGPDFDocumentRef в -dealloc. Кроме того, является ли CATiledLayer основным слоем вашего представления или просто подуровнем? Мое решение тестируется только с помощью CATiledLayer как подслоя, а не как основного. Я рекомендую вам просто добавить CATiledLayer в качестве подуровня, а не как замену основному слою представления. – Altealice

+0

Если это все еще не помогает, не возражаете ли вы добавить больше кода в свой пост, чтобы помочь? Например, когда вы запускаете CGPDFDocumentRef, где и как вы добавляете свой CATiledLayer, ваш -drawLayer: inContext :, и где вы выпускаете CGPDFDocumentRef. – Altealice

0

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

1

У меня была аналогичная проблема. я в конечном итоге установив переменную с плавающей точкой «зум» в моем TiledPDFView, который я поставил как zoomScale из PDFScrollView в методе UIScrollView делегата: scrollViewDidZoom

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

3

object.layer.contents = Nil

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

+1

Работал для меня тоже. Благодарю. – pt2ph8

3

TiledPDFView * pdfView;

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

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

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

Смежные вопросы