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
?
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
?
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;
Pourquoi passez-vous id comme argument ? N'est-il pas possible de passer facilement un NSNumber par exemple ? A quoi cela ressemblerait-il ?
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);
.)
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.
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);
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
});
});
}
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 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.
7 votes
Une référence que j'utilise plus souvent que je ne veux l'admettre : goshdarnblocksyntax.com
2 votes
fuckingblocksyntax.com :)