37 votes

Exécuter des blocs à partir de NSArray?

Je pensais justement, car vous pouvez traiter les blocs comme des objets si j'en crée deux, puis les ajoute à un NSArray. Existe-t-il un moyen de les exécuter à partir du tableau?

 int (^Block_001)(void) = ^{ return 101; };
int (^Block_002)(void) = ^{ return 202; };
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
 

EDIT: Mise à jour pour plus de clarté Excellente réponse de Per @ davedelong

 int (^Block_001)(void) = [^{ return 101; } copy];
int (^Block_002)(void) = [^{ return 202; } copy];
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];

[Block_001 release];
[Block_002 release];
 

60voto

Dave DeLong Points 156978

@KennyTM et @David sont corrects, mais votre code est potentiellement mauvais. Voici pourquoi:

Lors de la création d'un NSArray avec des objets, il sera retain les objets mis en elle. Dans le cas de blocs, c'est à l'aide de l' Block_retain fonction. Cela signifie que la matrice a retenu les blocs que vous avez créé, mais qui vivent sur la pile (les blocs sont l'un des très rares exemples d'Objective-C objets qui peuvent être créés sur la pile sans se plonger dans l'absurde de trucs). Cela signifie que dès que cette méthode de sorties, votre matrice de points aujourd'hui à la poubelle, parce que les blocs qu'il a été pointant vers n'existent plus. Pour ce faire correctement, vous devriez faire:

int (^Block_001)(void) = [^{ return 101; } copy];
int (^Block_002)(void) = [^{ return 202; } copy];
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];

[Block_001 release];
[Block_002 release];

En invoquant copy sur le bloc, vous avez explicitement déplaçant le bloc hors de la pile et dans le tas, où il peut rester en sécurité après la méthode/fonction se termine. Puis, après que vous avez ajouté les blocs de la matrice, vous devez équilibrer votre copy (en raison de la NARC règle) avec un appel ultérieur à l' release. Un sens?

29voto

David Gelhar Points 20703

Bien sûr, vous l'invoquez simplement avec () comme n'importe quel autre bloc, mais vous devez transtyper la valeur extraite de NSArray . Voici un exemple (avec un typedef ajouté, sinon ma tête me fait mal):

 typedef int (^IntBlock)(void);
IntBlock Block_001 = ^{ return 101; };
IntBlock Block_002 = ^{ return 202; };
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
int x = ((IntBlock)[array objectAtIndex:0]) (); // now x == 101
 

7voto

KennyTM Points 232647

Bien sûr vous pouvez.

 int (^x)(void) = [array objectAtIndex:0];
printf("%d\n", x()); // prints 101.
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X