Можно ли использовать Quartz 2D для создания UIImage на другом потоке? - PullRequest
3 голосов
/ 05 февраля 2012

Я хочу переместить некоторый код, который занимает пару секунд, чтобы сгенерировать UIImage в другом потоке, но я получаю контекстную ошибку при использовании

    UIGraphicsBeginImageContextWithOptions(size,false,0);

перед вызовом отправки для генерации изображения, говорящего "недопустимый контекст 0x0" для каждой операции, которую я пытаюсь сделать. Это вообще возможно?

Ответы [ 3 ]

13 голосов
/ 05 февраля 2012

Что нового в iOS: iOS 4.0 говорит это:

  • Рисование в графическом контексте в UIKit теперь является потокобезопасным. В частности:
    • Процедуры, используемые для доступа к графическому контексту и манипулирования им, теперь могут корректно обрабатывать контексты, находящиеся в разных потоках.
    • Рисование строк и изображений теперь поточно-ориентировано.
    • Использование объектов цвета и шрифта в нескольких потоках теперь безопасно.

Похоже, вы пробовали что-то вроде этого:

UIGraphicsBeginImageContextWithOptions(size,false,0);
dispatch_async(someQueue, ^{
    [UIColor.whiteColor setFill];
    UIRectFill(0, 0, 20, 20);
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        self.imageView.image = image;
    });
};

Это не сработает, потому что каждый поток имеет свой собственный стек графических контекстов (начиная с iOS 4.0). Вам нужно сделать это так:

dispatch_async(someQueue, ^{
    UIGraphicsBeginImageContextWithOptions(size,false,0);
    [UIColor.whiteColor setFill];
    UIRectFill(0, 0, 20, 20);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageView.image = image;
    });
};

UPDATE

Документация для UIGraphicsBeginImageContextWithOptions и другие графические функции UIKit теперь говорят

В iOS 4 и более поздних версиях вы можете вызывать эту функцию из любого потока вашего приложения.

Документация для UIColor говорит

Цветные объекты являются неизменяемыми, поэтому их можно безопасно использовать из нескольких потоков в вашем приложении.

Документация для UIFont говорит

Объекты шрифта являются неизменяемыми, поэтому их можно безопасно использовать из нескольких потоков в вашем приложении.

Однако , документация для дополнений, выводящих UIKit NSString, говорит

Методы, описанные в этом расширении класса, должны использоваться из основного потока вашего приложения.

Так что вы должны не попробовать что-то вроде [@"hello" drawAtPoint:CGPointZero withAttributes:attrs] из фонового потока.

1 голос
/ 05 февраля 2012

документы говорят:

Вы должны вызывать эту функцию только из основного потока вашего приложения.

Так что вызывать его в другом потоке не очень хорошая идея.

Вы можете попробовать вместо этого CoreGraphics и вызвать CGBitmapContextCreate().

0 голосов
/ 05 февраля 2012

Вы можете легко использовать CGContext для получения CGImage, находясь во вторичном потоке.

Вернитесь в основной поток, создайте UIImage из CGImage. Обратите внимание, что UIImage является неизменяемым типом контейнера - это не должно приводить к глубокой копии данных изображения.

...