Pregunta

Estoy tratando de entender cómo usar bloques en iOS. He leído los documentos de Apple, pero, como de costumbre, son vagos e incompletos y no se mencionan varios bits de información esenciales. También he buscado en Google sin éxito. Esto es lo que estoy tratando de hacer como un ejercicio para entender eso.

He creado un bloque para leer una cadena y comparar la cadena con la lectura anterior. Si las cadenas no son las mismas, devuelva sí, si son las mismas, devuelva no.

Así es como lo hice:

Declaré esto en .h

BOOL (^differentStrings)(void);

Declaré esto en .m, dentro de ViewDidload en un ViewController

__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){

    currentString = [self getString];
    NSLog(@"%@", currentString); // not printing anything on console

    if (![currentString isEqualToString:previousString]) {
        previousString = currentString;
        return YES;
    } else {
        return NO;
    }
};

Así es como uso: tengo un hilo que hace esto:

if (differentStrings)
  NSLog (@"strings are different);

Estos son los problemas que tengo:

  1. El bloque siempre regresa sí (las cadenas son diferentes)
  2. No me siento cómodo declarando esto dentro de Vidididload. ¿Cómo debo declarar esto, para que pueda usarlo a nivel mundial como método? ¿Debo poner esto como lo haría con un método?
  3. Estoy llamando a un método "gettring" dentro del bloque. ¿Está bien?
  4. Me resulta extraño declarar las variables de bloque en .m. Como veo, debería declarar las variables de bloque en .h y luego usarlas en .m. He intentado hacer eso, pero recibí un error.
  5. He configurado un punto de depuración en la primera línea del bloque, pero no se detiene allí;
  6. La línea NSLOG dentro del bloque no imprime nada. ¿No se llama el bloque?

¿Pueden ayudarme con esto?

¿Fue útil?

Solución

Estás malinterpretando cómo funcionan los bloques. (Está bien, eso es un poco obvio). De la misma manera que previousString es una variable que apunta a un nsstring, differentStrings es una variable que apunta a un bloquear. No es el resultado de ejecutar el bloque, sino más bien el bloque en sí. Es decir, después de hacer esto:

__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){

    currentString = [self getString];
    NSLog(@"%@", currentString); // not printing anything on console

    if (![currentString isEqualToString:previousString]) {
        previousString = currentString;
        return YES;
    } else {
        return NO;
    }
};

differentStrings es una variable que apunta al bloquear. Por lo tanto, cuando haces esto:

if (differentStrings)

... simplemente estás revisando si differentStrings contiene algo más que 0 o nulo. Dado que contiene un bloque, no está vacío, por lo que se evalúa en verdad.

Recuerda: differentStrings es una variable de bloque, no una variable BOOL. Contiene un bloque (una función, si lo desea), que cuando llamó devolverá un bool. Por lo tanto, para ejecutar el bloque, debe llamarlo. Como esto:

differentStrings();

O, en su caso:

if (differentStrings()) {
    NSLog (@"strings are different");
}

Editar: Como se señaló en los comentarios, ya que differentStrings es una variable de instancia, necesitas copy Es, como llamarías retain en cualquier otro objeto asignado a una variable de instancia. (Por razones técnicas que no entraré ahora, siempre debes usar copy con bloques en lugar de retain.) Del mismo modo, tendrás que llamar release sobre él en algún momento más tarde, tal vez en tu dealloc método.

Otros consejos

No creo que realmente estés ejecutando el bloque. Creo que tu código debería ser

if (differentStrings())
{
    NSLog (@"strings are different);
}

Trate un bloque como una función. Creo que solo estabas revisando para ver si el bloque había sido definido, no ejecutarlo.

Además, si no necesita acceder a un nsstring fuera del bloque, podría deshacerse del __block calificador y mover el currentString Declaración dentro del bloque.

Si necesita otro recurso en bloques, los cubro en la sesión de otoño de mi curso avanzado de desarrollo de iOS en iTunes u. Describo la sintaxis de bloque en la sesión de comprensión de cacao y su uso en el despacho de Grand Central dentro de la sesión de múltiples lecturas. Las notas del curso también tienen enlaces a algunas aplicaciones de muestra que usan bloques de diferentes maneras.

Tampoco puedo recomendar lo suficiente como para ver el WWDC 2010 Sesiones de video 206 - Presentación de bloques y gran envío central en iPhone y 211 - Simplificando el desarrollo de aplicaciones de iPhone con Grand Central Dispatch.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top