149 votes

Objective-C : passer un bloc en tant que paramètre

Comment puis-je passer un Block à un Function / Method ?

J'ai essayé - (void)someFunc:(__Block)someBlock en vain.

ie. Quel est le type pour un Block ?

7 votes

Une référence que j'utilise plus souvent que je ne veux l'admettre : goshdarnblocksyntax.com

2 votes

264voto

Jonathan Grynspan Points 32291

Le type d'un bloc varie en fonction de ses arguments et de son type de retour. Dans le cas général, les types de blocs sont déclarés de la même manière que les types de pointeurs de fonctions, mais en remplaçant l'attribut * avec un ^ . L'une des façons de transmettre un bloc à une méthode est la suivante :

- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;

Mais comme vous pouvez le constater, c'est un peu compliqué. Vous pouvez à la place utiliser un typedef pour rendre les types de blocs plus propres :

typedef void (^ IteratorBlock)(id, int);

Ensuite, nous transmettons ce bloc à une méthode, comme suit :

- (void)iterateWidgets:(IteratorBlock)iteratorBlock;

0 votes

Pourquoi passez-vous id comme argument ? N'est-il pas possible de passer facilement un NSNumber par exemple ? A quoi cela ressemblerait-il ?

7 votes

Vous pouvez certainement passer un argument fortement typé tel que NSNumber * o std::string& ou toute autre chose que vous pourriez passer comme argument d'une fonction. Ce n'est qu'un exemple. (Pour un bloc équivalent, à l'exception du remplacement de id con NSNumber , le typedef serait typedef void (^ IteratorWithNumberBlock)(NSNumber *, int); .)

0 votes

Ceci montre la déclaration de la méthode. L'un des problèmes des blocs est que le style de déclaration "désordonné" ne permet pas d'écrire clairement et facilement l'appel de méthode réel avec un véritable argument de bloc.

52voto

quaertym Points 2239

Cela peut être utile :

- (void)someFunc:(void(^)(void))someBlock;

0 votes

Il manque une parenthèse

0 votes

Celui-ci a fonctionné pour moi alors que le précédent ne l'a pas fait. Merci mon pote, c'était en effet très utile !

22voto

WinDMak3r Points 146

Vous pouvez procéder comme suit, en passant le bloc en tant que paramètre de bloc :

//creating a block named "completion" that will take no arguments and will return void
void(^completion)() = ^() {
    NSLog(@"bbb");
};

//creating a block namd "block" that will take a block as argument and will return void
void(^block)(void(^completion)()) = ^(void(^completion)()) {
    NSLog(@"aaa");
    completion();
};

//invoking block "block" with block "completion" as argument
block(completion);

8voto

Dren Points 11

Une autre façon de passer un bloc est d'utiliser des fonctions dans l'exemple ci-dessous. J'ai créé des fonctions pour effectuer n'importe quelle opération en arrière-plan et dans la file d'attente principale.

fichier blocks.h

void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));

fichier blocks.m

#import "blocks.h"

void performInBackground(void(^block)(void)) {
    if (nil == block) {
        return;
    }

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}

void performOnMainQueue(void(^block)(void)) {
    if (nil == block) {
        return;
    }

    dispatch_async(dispatch_get_main_queue(), block);
}

Ensuite, il faut importer blocks.h lorsque c'est nécessaire et l'invoquer :

- (void)loadInBackground {

    performInBackground(^{

        NSLog(@"Loading something in background");
        //loading code

        performOnMainQueue(^{
            //completion hadler code on main queue
        });
    });
}

6voto

iiFreeman Points 1521

Vous pouvez également définir le bloc comme une propriété simple si cela vous convient :

@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);

assurez-vous que la propriété du bloc est "copy" !

et, bien sûr, vous pouvez également utiliser typedef :

typedef void (^SimpleBlock)(id);

@property (nonatomic, copy) SimpleBlock someActionHandler;

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