2012-05-03 4 views
9

Solo estoy tratando de controlar los bloques. Entiendo el concepto Son como indicadores de función, pero en realidad son objetos; puedes declarar una variable de bloque y asignarle un valor de bloque; llamarlo como una función; se "congelan a tiempo", por falta de un término, cuando se ejecutan, etc. He creado algunos bloques y los he ejecutado con éxito, en algunos formatos diferentes, pero cuando se trata de usarlos de forma -ya sea con un typedef o sin - estoy teniendo muchos problemas. Por ejemplo, aquí hay una interfaz de objeto que creé, solo para obtener un control sobre la sintaxis. Casi no tengo idea de cómo implementarlo.Objective-C: typedef'd a block, lo usó en una declaración de método. ¿Cómo implemento esto?

// AnObject.h 

#import <Foundation/Foundation.h> 

// The idea with the block and the method below is for the block to take 
// an int, multiply it by 3, and return a "tripled" int. The method 
// will then repeat: this process however many times the user wants via 
// the howManyTimes parameter and return that value in the form of an int. 

typedef int (^triple)(int); 

@interface AnObject : NSObject 
{ 
    int num; 
} 

-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock; 

@end 

Esto es lo que tengo para una implementación, hasta el momento:

#import "AnObject.h" 

@implementation AnObject 

@synthesize num; 

-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock { 
    for (int i = 0; i <= howManyTimes; i++) { 
     // What the heck am I supposed to put here? I'm baffled by the 
     // syntax over and over again. 
    } 
} 

@end 

Sé que no estoy dirigiendo a la variable de instancia todavía. Nuevamente, este es un borrador, simplemente tratando de entender cómo funcionan los bloques. ¿Incluso estoy declarando este método correcto? Estoy leyendo la programación Objective-C de Big Nerd Ranch, el artículo de Mike Clark sobre bloques de Pragmatic Studio y varios hilos SO. No puedo encontrar nada relevante. Gracias.

EDITAR: XCode 4.3.2, si es importante.

OTRA EDICIÓN: Ok. Usando el ejemplo de BJ (ligeramente modificada), creo que he llegado con una forma muy complicada de multiplicar por 5 3. :)

// BJ's implementation: 

-(int)repeat:(int)howManyTimes withBlock:(Triple)someBlock { 

    int blockReturnValue; 

    for (int i = 0; i <= howManyTimes; i++) { 
     blockReturnValue = someBlock(i); 
    } 
    return blockReturnValue; 
} 

principal:

... 
    @autoreleasepool 
    { 
     AnObject *obj = [[AnObject alloc] init]; 

     NSLog(@"%d", [obj repeat: 5 withBlock:^(int number) { 
      return number * 3; 
     }]); 

    } 
    return 0; 
... 

y la salida es:

15 

Ahora, está retrocediendo 15, porque el bloque que definí como argumento se ejecuta solo una vez, ¿verdad? Multiplica "número", que es 5 en este caso, por 3 y congela esa respuesta, ¿verdad? Estoy seguro de que acabo de crear un método completamente inútil, y todavía no entiendo cómo utilizar los beneficios/características de un bloque. ¿Estoy en lo correcto?

/* ** * ** * ** * ** * ** * ** * ** ACTUALIZACIÓN ** * ** * ** * ** * ** * ** * ** */

ACTUALIZACIÓN: entiendo lo que estás diciendo, CRD. Solo una corrección, para cualquier programador nuevo que pueda estar leyendo esto, obteniendo una salida diferente y diciendo "Que?" Su bucle debe ser:

for (int i = 0; i < howManyTimes; i++) 
      value = someBlock(value); 

... o ...

(i = 1; i <= howManyTimes; i++) 

... para obtener la respuesta 243.

Y, sí, esto es exactamente lo que inicialmente estaba tratando de hacer con este código. Al menos eso es lo que pensé que se suponía que estaba pasando. Resulta que la intención del autor no era triplicar un número, almacenar ese valor, triplicar el valor almacenado, almacenar eso ... etc., sino simplemente imprimir x * 3 para los números 1-5 (3, 6, 9, 12, 15).

Aquí está el producto final. Acabo de tipear un bloque que toma un int y devuelve un int, llamado Tripler. También cambié el nombre del argumento de "someBlock" a "triple" para indicar más claramente el uso previsto del bloque. Creo que esos son los únicos cambios al código.

/******************** interface ********************/ 


#import <Foundation/Foundation.h> 

typedef int (^Tripler)(int); 

@interface AnObject : NSObject 

-(void)iterateFromOneTo:(int)number withBlock:(Tripler)triple; 

@end 

/******************** implementation ********************/ 


#import "AnObject.h" 

@implementation AnObject 

-(void)iterateFromOneTo:(int)number withBlock:(Tripler)triple { 
    for (int i = 1; i <= number; i++) { 
     NSLog(@"%d", triple(i)); 
    } 
} 

@end 

/******************** main.m ********************/ 


#import "AnObject.h" 
#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool 
    { 
     AnObject *obj = [[AnObject alloc] init]; 

     [obj iterateFromOneTo:5 withBlock:^(int number) { 
      return number * 3; 
     }]; 
    } 
    return 0; 
} 

Como podrán imaginar, la salida resultante es:

2012-05-05 17:10:13.418 Untitled 2[71735:707] 3 
2012-05-05 17:10:13.445 Untitled 2[71735:707] 6 
2012-05-05 17:10:13.446 Untitled 2[71735:707] 9 
2012-05-05 17:10:13.446 Untitled 2[71735:707] 12 
2012-05-05 17:10:13.447 Untitled 2[71735:707] 15 

yo estaba haciendo que sea mucho más complicado de lo que debía ser. Perdón por explicarlo tan mal en el OP. ¡Gracias por tu ayuda! /¿hilo? :)

+0

Ir a través de este bloque Explicación ... – shankar

Respuesta

7

Simplemente llame al bloque como una función normal de C.

-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock { 
    for (int i = 0; i <= howManyTimes; i++) { 
     int blockReturnValue = someBlock(i); 
     // do something with blockReturnValue 
    } 
} 

Update después de su "hacer otras modificaciones"

No, el bloque que pasa como un argumento se ejecuta cinco veces, cada paso a través del bucle.

  • La primera vez, invoca el bloque con 1 como el argumento, y vuelve 3. Almacena eso en blockReturnValue, luego pasa a la siguiente iteración del ciclo.
  • La segunda vez, invoca el bloque con 2 como argumento y vuelve a 6. Almacena eso en blockReturnValue, sobrescribiendo por completo el valor que almacenamos allí en la pasada anterior.
  • La tercera vez, invoca el bloque con 3 como argumento y vuelve a 9. Nuevamente, sobrescribe el valor en blockReturnValue.
  • La cuarta vez, almacenamos 12 en blockReturnValue.
  • La quinta vez, almacenamos 15 en blockReturnValue.

Luego salir del bucle, y volver 15. Así que sí, estás en lo correcto que usted ha hecho un método inútil multiplicar por 3. Pero lo estás haciendo de una manera que también hace un montón de cálculos inútiles.

+0

http://www.highoncoding.com/Articles/852_Introduction_to_Objective_C_Blocks.aspx bien. Tal vez es más simple de lo que imagino. Trabajando en eso ahora. – baptzmoffire

+0

Ok. Por favor, consulte "EDITAR ADICIONALMENTE": Gracias por la ayuda, BJ. – baptzmoffire

+1

Creo que tengo un IQ de programación bajo, desafortunadamente. : P Tengo la esencia de lo que está pasando. Debería ser más claro, pero creo que es solo la sintaxis lo que me está dando resultados. Eso es lo que me impide seguir lo que realmente está sucediendo. Voy a investigar tanto sobre bloques como pueda hasta que finalmente vea cómo funcionan y cuándo usarlos correctamente. Muchas gracias por su ayuda y paciencia. – baptzmoffire

8

Al leer su pregunta comprendí, o quizás entendí mal, que su intención era producir el resultado de aplicar su bloque n veces; p.ej. si aplicó una función de triplicar dos veces, obtendría el valor original multiplicado por nueve.

Sólo en caso de que ayuda, aquí está el código para hacer esto:

@interface AnObject 

typedef int (^monadic)(int); // an function which takes an int and return an int 

- (int) repeat:(int)howManyTimes for:(int)value withBlock:(monadic)someBlock; 

@end 

@implementation AnObject 

- (int) repeat:(int)howManyTimes for:(int)value withBlock:(monadic)someBlock 
{ 
    for (int i = 0; i < howManyTimes; i++) 
     value = someBlock(value); 

    return value; 
} 

@end 

Ahora llaman a esto con:

AnObject *myObject = [AnObject new]; 

int z = [myObject repeat:5 
        for:1 
       withBlock: ^(int number) 
          { 
          return number * 3; 
          } 
     ]; 

y z tendrá el valor 243.

+0

Gracias por la respuesta, CRD. Apreciamos que tomes el tiempo. Ver la "ACTUALIZACIÓN" arriba. – baptzmoffire

+0

@baptzmoffire - correcto, oops :-(corrigió el error ortográfico, ahora produce 243! – CRD

+0

Gracias de nuevo, CRD. :) – baptzmoffire

1
@import Foundation; 

typedef int(^MyBlockType)(int); 

@implementation NSObject(extra) 
+ (int)invokeBlock:(MyBlockType)block withArgument:(int)arg 
{ 
    return block(arg); 
} 
@end; 

int main() { 
    @autoreleasepool { 
     NSLog(@"executeBlock(3) returns %d", 
       [NSObject invokeBlock:^(int param) { return param * param; } withArgument:3]); 
    } return 0; 
} 
Cuestiones relacionadas