2012-06-07 13 views
9

Estoy un poco confundido acerca de UIGraphicsBeginImageContextWithOptions y el enhebrado porque de acuerdo con UIKit Function ReferenceUIGraphicsBeginImageContextWithOptions solo debe invocarse en el hilo principal. Cuando se lo llama crea un contexto basado en mapa de bits, que está listo para ser manipulado ya sea con las funciones de CoreGraphics o con métodos como - drawInRect: para UIImage, -drawInRect:withFont: para NSString y así sucesivamente. Para el dibujo de CoreGraphics todo está claro: pasas un argumento CGContextRef que se está manipulando para cada función, pero los métodos de dibujo UIKit usan el contexto actual en la pila. En las notas de la versión de What's New in iOS 4.0 está escrito queUIGraphicsBeginImageContextWithOptions y Multithreading

Dibujo de un contexto gráfico en UIKit ahora es seguro para subprocesos. Específicamente:
- Las rutinas utilizadas para acceder y manipular los gráficos
contexto ahora pueden manejar correctamente contextos que residen en diferentes subprocesos .
- El dibujo de cadenas y de imágenes ahora es seguro para subprocesos.
- Usar objetos de fuente de color y en varios subprocesos ahora es seguro.

Hasta ahora todo bien. La parte interesante es que tengo un proyecto, donde realizo dibujos intensivos y creo varias imágenes creando contexto con UIGraphicsBeginImageContextWithOptions, pero cuando estas operaciones pasaron más tiempo y acabo de mover el dibujo en un hilo de fondo y cuando estaba listo Muéstrelas en la pantalla con algunas animaciones y todo funciona bien, sin fallas, sin pérdidas. Las imágenes se dibujan como se espera y parece que UIGraphicsBeginImageContextWithOptions crea un contexto para el hilo de fondo y todo parece estar bien.
Así que mis preguntas son:
- ¿Por qué es necesario llamar al UIGraphicsBeginImageContextWithOptions solo en el hilo principal, ya que parece funcionar bien en el fondo?
- Cómo usar UIImage-drawInRect: método, por ejemplo, en un hilo de fondo, donde no tengo un contexto actual y parece que no puedo crear uno porque no puedo llamar al UIGraphicsBeginImageContextWithOptions allí?
- ¿Cuál es el enfoque correcto para la manipulación de imágenes de fondo utilizando los métodos de UIKit? (Sé que también puedo usar CGBitmapContextCreate, pero ni empuja el contexto creado a la pila de contexto ni parece ser capaz de hacerlo yo mismo para usar -drawInRect: método de UIImage)?

Respuesta

21

Entonces, después de un par de días de investigación, ¿cómo es que manipular el contexto de UIKit es seguro para subprocesos y aún así no parece poder crear uno en un hilo distinto del principal porque UIGraphicsBeginImageContextWithOptions "debería llamarse sólo en el hilo principal ", pero aún así funciona perfectamente bien y después de leer algunas pequeñas publicaciones sobre el tema y discutirlo con otros chicos en los foros de desarrolladores de Apple puedo afirmar claramente que, lo que se dice en la documentación sobre UIGraphicsBeginImageContextWithOptions, UIGraphicsPushContext y UIGraphicsPopContext es INCORRECTO y esos métodos podrían ser llamados y el contexto utilizado en otro hilo sin problemas.Por lo tanto, UIGraphicsBeginImageContextWithOptions, UIGraphicsPushContext y UIGraphicsPopContext son thread-safe.

+3

Puedo confirmar esto. Este fue un error de documentación en iOS5 SDK y antes (si tiene acceso a los videos de la WWDC 2012, consulte la sesión 211 y los documentos del SDK de iOS6). –

+0

También es muy importante llamar a UIGraphicsEndImageContext() o las cosas comienzan a ponerse raras con la CPU. – bentford

+2

La documentación se ha corregido: 'En iOS 4 y posterior, puede llamar a esta función desde cualquier subproceso de su aplicación. – graver

0

Respuesta parcial: Use UIGraphicsPushContext para insertar su propio contexto de CG en la parte superior de la pila de "contexto de UIKit" y todo (de ese hilo, como interpreto la documentación de Apple) se reflejará en eso. No olvides usar UIGraphicsPopContext para abrirlo desde la pila de contexto de UIKit.

Esto se aplica a todas las operaciones de dibujo de UIKit; por ejemplo, dibujo UIImage s, como usted pidió. Presiona un contexto, dibuja y luego abre el contexto.

+0

Esa fue una de mis ideas, pero desafortunadamente el documento dice: 'Deberías llamar a esta función sólo desde el hilo principal de tu aplicación. 'Tanto para' UIGraphicsPushContext' como 'UIGraphicsPopContext' – graver

+2

No puedo recordar cuál y yo no puedo encontrarlo, pero vi estas cosas cubiertas en gran detalle en un video de la WWDC de 2011 o 2010. Mi intuición de lo que recuerdo es que parte de la documentación es sutilmente engañosa y que todo funcionará de una manera sensata si solo sigue algunas reglas del video. (No esperaría que apueste la granja con este consejo, pero creo que si encontrara el video respondería a sus preguntas.) – Jesper

+0

Voy a echar un vistazo ahora y escribiré una respuesta. – graver