Остановить рисование CATiledLayer
Можно ли остановить 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 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);
}
Ответы
Ответ 1
этот пост помог мне решить мою собственную проблему с CATiledLayer. В качестве примера я использовал TiledPDFview.m из документации Apple.
Поскольку в какой-то момент мне нужно перерисовать весь вид и все плитки, я использую свойство CATiledLayer как свойство.
При выходе и освобождении диспетчера представлений он сработал с [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 why it commented out:
// [self.tiledLayer release], self.tiledLayer=nil;
//release the other viewcontroller stuff...
[super dealloc];
}
Это работает для меня. Надеюсь, это поможет кому-то.
Ответ 2
Удалите 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: реализация в ваш контроллер представления.
Затем в вашем представлении контроллер dealloc, отпустите его как:
[tiledLayer removeFromSuperlayer];
tiledLayer.delegate = nil;
CGPDFDocumentRelease(pdf);
Обратите внимание, что вы не можете сделать это в подклассе UIView, поскольку drawLayer: inContext: будет конфликтовать с основным слоем UIView.
Ответ 3
object.layer.contents = Nil
Это должно дождаться завершения потока. Это помогло мне в моем случае.
Ответ 4
TiledPDFView * pdfView;
В dealloc класса просмотра pdfView, напишите ниже строку кодов.
- (void)dealloc {
if (nil != self.pdfView.superview) {
self.pdfView.layer.delegate = nil;
[self.pdfView removeFromSuperview];
}
}
Это работает для меня. Надеюсь, это поможет.
Ответ 5
У меня была аналогичная проблема.
Я закончил настройку переменной float "zoom" в моем TiledPDFView, которую я установил как zoomScale PDFScrollView в методе делегата UIScrollview: scrollViewDidZoom
Затем в моем методе drawLayer внутри TiledPDFView я вызывал только содержимое этого метода, если переменная float "zoom" была выше 2.
Это устраняет любые проблемы, связанные с тем, кто покидает представление без масштабирования. Это может быть не идеально для вашего случая, так как эта ошибка все еще возникает, если кто-то увеличивает изображение выше 2, а затем быстро освобождает диспетчер представлений, но вы можете найти подобный метод для покрытия всех баз.
Ответ 6
Похоже, вы делаете то же самое, что и я, который заимствует код ZoomingPDFView и интегрирует его в ваш проект. Если ваши методы делегатов UIScrollView в PDFScrollView не изменяются, вы можете решить свою проблему, просто комментируя обе строки вашего метода dealloc (в TiledPDFView). В любом случае, это должно происходить только тогда, когда вы убиваете родительский вид.