Рисунок CoreGraphics вызывает предупреждения памяти / сбой на iOS 7
После обновления моего iPad (mini) до iOS7 я почувствовал, что мое приложение для рисования отстает и падает после нескольких ударов.
Теперь, когда я запускаю приложение с инструментами / инструментом выделения памяти в xcode 5, я вижу, что категория растровых данных VM: CG быстро заполняется при рисовании на экране. Кажется, существует множество вызовов CGDataProviderCreateWithCopyOfData, каждый размером 3,00 МБ. После непрерывного рисования приложение получает предупреждения памяти и обычно завершает работу.
Код в основном прокладывает пути к изображению, более или менее так:
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
На iOS7/iPad это очень запаздывает и имеет проблемы с памятью, в то время как на iOS6 это было довольно быстро и не имело отрицательного следа памяти.
Когда я запускаю этот код в не- Retina версии iPhone, вызовы CGDataProviderCreateWithCopyOfData имеют размер 604 Кб, и только один или два "активны" одновременно. Чертеж плавный и быстрый, без предупреждений памяти и замедления.
Что произошло с iOS6 до iOS7 в отношении CoreGraphics и изображенийконтекстов?
Извините за любые ошибки в жаргоне или другие возможные глупые ошибки. Еще нуб, занимаюсь разработкой под iOS в свободное время.
2 ответа
Я поместил свой код для рисования в авто-релиз, и это решило мою проблему.
Например:-
@autoreleasepool {
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
В общем случае я решил создать класс Canvas UIView, который обрабатывает все операции рисования. Я пишу в кэшированный CGImageRef, а затем объединяю кеш с UIImage в соответствии с этим:
Мой пользовательский метод drawRect выглядит примерно так:
- (void)drawRect:(CGRect)rect
{
// Drawing code
UIGraphicsBeginImageContext(CGSizeMake(1024, 768));
CGContextRef context = UIGraphicsGetCurrentContext();
CGImageRef cacheImage = CGBitmapContextCreateImage(cacheContext);
CGContextDrawImage(context, self.bounds, cacheImage);
// Combine cache with image
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
CGImageRelease(cacheImage);
UIGraphicsEndImageContext();
}
При касании Moved я вызываю метод drawLine, который выполняет некоторую интерполяцию кривой, регулировку размера кисти и сужение конечной линии, а затем выполняет [self setNeedsDisplay];
Кажется, это хорошо работает в iOS7. Извините, если я не могу быть более конкретным, но я бы не стал публиковать реальный производственный код из моего приложения:)