Рисование в фоновом потоке на iOS - PullRequest
6 голосов
/ 09 октября 2011

У меня есть вид с очень сложной логикой рисования (это вид карты, который опирается на данные ГИС). Выполнение этого рисунка в главном потоке блокирует пользовательский интерфейс и делает приложение не отвечающим. Я хочу переместить рисунок в фоновый поток, например, с помощью NSOperation.

Каков наилучший способ структурировать это?

В настоящее время я рисую в CGContext с отключенной памятью, а затем преобразую его в CGImageRef, который я отправляю в представление для перетаскивания в главном потоке. К сожалению, это занимает много памяти, и кажется, что ускорение GPU больше не используется, поскольку оно немного медленнее. Есть ли какой-нибудь способ рисования непосредственно в виде из фонового потока? Я знаю, что UIKit не является многопоточным, но, возможно, есть какой-то способ блокировки вида, пока я рисую?

Ответы [ 2 ]

6 голосов
/ 11 октября 2011

Вне iOS 4.0, рисунок безопасен для потоков .Возможно, вам придется создать CGContext самостоятельно, но нет причины, по которой вы не можете рисовать в фоновом потоке.

Тем не менее, большинство операций UIKit - нет.Если вам нужно сделать это, вы всегда можете подготовиться в фоновом потоке, а затем использовать performOnMainThread при необходимости.Там даже waitUntilDone.Тем не менее, вы должны использовать NSOperation и NSOperationQueue, по-видимому.

1 голос
/ 12 октября 2011

Я никогда не сталкивался с такой ситуацией на iPhone, но на Mac у меня однажды была похожая проблема.

  1. Используйте CGLayer , чтобы делегировать активность рисования автономных контекстов.
  2. Попробуйте добавить таймер для текущего NSRunLoop и через определенный промежуток времени выполните ваши графические команды. Это должно выглядеть примерно так ...

...

kRenderFPS 25.0 //This is Maximum value

renderTimer = [[NSTimer timerWithTimeInterval:(1.0 / (NSTimeInterval)kRenderFPS) target:viewobject selector:@selector(RenderUI:) userInfo:nil repeats:YES] retain];


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSDefaultRunLoopMode];


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSModalPanelRunLoopMode];


[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSEventTrackingRunLoopMode];

//In view class
-(void)RenderUI:(id)param
{
    [self setNeedsDisplayInRect:[self bounds]];
}

Это должно сработать.

Также попробуйте попробовать ваш процесс и проверить, кто использует процессор. Это сделает пользовательский интерфейс отзывчивым и очень быстрым.

Проблема производительности, о которой вы упомянули, может быть связана с чем-то другим. Попробуйте процесс выборки процессора. Это даст вам представление о том, кто на самом деле использует процессор.

...