actualizar el hilo de la interfaz de usuario desde una función C en iOS

Estoy trabajando con un programa en C para intentar usarlo en mi aplicación iOS con la menor modificación posible. El programa C realiza muchos cálculos en un conjunto de entradas.

En el lado de iOS, estoy usando el siguiente código para crear un hilo para ejecutar los cálculos, y también para tener un mecanismo para informar cuando esté completo (actualmente, actualiza un UILabel os "testLabel" cuando está completo):

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    char *testChar = startProgram( nx, ny, nz ); // this is where I call the C program 

    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *tempString = [[NSString alloc]initWithCString: testChar ];

        testLabel.text = tempString;

        [tempString release];

    });
});

Esto parece funcionar, obtengo mis resultados y mi interfaz de usuario permanece receptiva.

Sin embargo, quiero comunicarme desde la rutina C de vuelta a la interfaz de usuario mientras se realizan los cálculos para obtener el estado y para devolver algunos datos de forma incremental.

Entonces mi programa C sería algo como esto:

char* startProgram( int nx, int ny, int nz )
{
    setupEverything(); // this is just pseudo code for clarity
    for( int i = 0; i < nz; i++ )
    {
        doMajorCalculations();

        reportBackToUI( someResults ); // This is what I would LIKE to do
    }
}

Vi un hilo aquí sobre pasar "yo", pero no creo que el "yo" si se pasa arriba sería mi "yo" de clase. Además, lo intenté y obtuve un error en el lado C de las cosas, diciendo que no reconocía el tipo "id". Cambié el tipo de "id" por el nombre de la clase y me dijo que el parámetro era incorrecto.

¿Alguna idea sobre la mejor manera de implementar esto?

Gracias por tu ayuda.

preguntado el 10 de mayo de 11 a las 14:05

2 Respuestas

Tal vez lo que desee es tener un bloqueo como devolución de llamada para informar resultados parciales a la persona que llama. Algo como esto:

char* startProgram( int nx, int ny, int nz, void(^reportBackToUI)(int) )
{
    setupEverything(); // this is just pseudo code for clarity
    for( int i = 0; i < nz; i++ )
    {
        doMajorCalculations();

        reportBackToUI( someResults ); // This is what I would LIKE to do
    }
}

Entonces el cliente podría llamar startProgram usando algo como:

return startProgram(42, 12, 20, ^(int someResults) {
           dispatch_async(dispatch_get_main_queue(), ^{
              // Update UI in some way.
           });         
       });

De esta manera, su código no dependerá de qué o cómo lo haga el cliente y use la devolución de llamada de progreso para. También es una buena inyección de dependencia.

Si no es posible usar bloques (¿Es posible que el código del modelo deba ser C puro para funcionar en otras plataformas?) entonces puede cambiar el bloque por un puntero de función.

contestado el 10 de mayo de 11 a las 18:05

Acabo de notar el dispatch_async en el bloque, eso debería funcionar. disculpas por no haber captado eso. - davydotcom

@davydotcom: Por eso tengo dispatch_async(dispatch_get_main_queue(), ^{… en el ejemplo de cómo utilizar la devolución de llamada. Este es el jugo mágico que ejecuta código en el hilo principal. - PeyloW

declarar un vacío de c global *

void* sipUACObj;

Y asígnele el objeto de clase objetivo-c en su inicializador de clase

sipUACObj = self;

Ahora, siempre que necesite invocar algo de la función C, haga lo siguiente,

  ObjcClass *obj = (ObjcClass*) sipUACObj;
  [obj someMethod:arg1 Arg2:arg2];

Esto llamará a la función objetivo-C correspondiente y puede invocar el hilo principal de la IU en esa función.

Puede crear una clase singleton y asignarla al puntero void en su inicialización y luego hacer lo necesario en su función C.

contestado el 10 de mayo de 11 a las 18:05

Probé la otra solución primero y funcionó. Sin embargo, el tuyo parece que también funcionaría. Gracias por tu tiempo. - W. Wright

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.