Wie kann ich ein Blockan ein Function/ übergeben Method?
Ich versuchte es - (void)someFunc:(__Block)someBlockohne Erfolg.
dh. Was ist der Typ für ein Block?
Wie kann ich ein Blockan ein Function/ übergeben Method?
Ich versuchte es - (void)someFunc:(__Block)someBlockohne Erfolg.
dh. Was ist der Typ für ein Block?
Antworten:
Der Typ eines Blocks hängt von seinen Argumenten und seinem Rückgabetyp ab. Im allgemeinen Fall werden Blocktypen genauso deklariert wie Funktionszeigertypen, jedoch durch *a ersetzt ^. Eine Möglichkeit, einen Block an eine Methode zu übergeben, ist folgende:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
Aber wie Sie sehen können, ist das chaotisch. Sie können stattdessen a verwenden typedef, um Blocktypen sauberer zu machen:
typedef void (^ IteratorBlock)(id, int);
Und dann übergeben Sie diesen Block an eine Methode wie folgt:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
NSNumber *oder std::string&oder irgendetwas anderes übergeben, das Sie als Funktionsargument übergeben könnten. Dies ist nur ein Beispiel. (Für einen Block, der mit Ausnahme des Ersatzes gleichwertig ist idmit NSNumberder typedefwäre typedef void (^ IteratorWithNumberBlock)(NSNumber *, int);.)
NS_NOESCAPE, aber enumerateObjectsUsingBlockmir wurde gesagt, dass sie nicht ausgeblendet werden, aber ich sehe NS_NOESCAPEnirgendwo auf der Website etwas, und es wird in den Apple-Dokumenten überhaupt nicht erwähnt, dass es ausgeblendet wird. Kannst du helfen?
Die einfachste Erklärung für diese Frage ist die Befolgung dieser Vorlagen:
1. Block als Methodenparameter
Vorlage
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
Beispiel
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
Andere Verwendung von Fällen:
2. Als Eigenschaft blockieren
Vorlage
@property (nonatomic, copy) returnType (^blockName)(parameters);
Beispiel
@property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
3. Blockieren Sie als Methodenargument
Vorlage
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
Beispiel
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4. Block als lokale Variable
Vorlage
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
Beispiel
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5. Als typedef blockieren
Vorlage
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
Beispiel
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
Sie können dies tun, indem Sie den Block als Blockparameter übergeben:
//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);
Eine weitere Möglichkeit, den Block mit den Funktionen с im folgenden Beispiel zu übergeben. Ich habe Funktionen erstellt, um alles im Hintergrund und in der Hauptwarteschlange auszuführen.
blocks.h Datei
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
blocks.m Datei
#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);
}
Als import blocks.h wenn nötig und rufen Sie es auf:
- (void)loadInBackground {
performInBackground(^{
NSLog(@"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
Sie können Block auch als einfache Eigenschaft festlegen, wenn dies für Sie gilt:
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
Stellen Sie sicher, dass die Blockeigenschaft "copy" ist!
und natürlich können Sie auch typedef verwenden:
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
Außerdem rufen Sie einen Block mit der üblichen c-Funktionssyntax auf oder rufen ihn auf
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
Mehr Infos zu Blöcken hier
Ich neige immer dazu, die Blocksyntax zu vergessen. Das fällt mir immer ein, wenn ich einen Block deklarieren muss. Ich hoffe es hilft jemandem :)
Ich habe einen CompletionBlock für eine Klasse geschrieben, die die Werte der Würfel zurückgibt, nachdem sie geschüttelt wurden:
Definieren Sie typedef mit returnType ( .hobige @interfaceDeklaration)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);Definiere a @propertyfür den Block ( .h)
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;Definieren Sie eine Methode mit finishBlock( .h)
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;Insert vorherige definierte Methode in .mDatei und verpflichten finishBlockzu @propertydefiniert vor
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}Um completionBlockeinen vordefinierten variablen Typ an ihn auszulösen (Vergessen Sie nicht zu prüfen, ob der completionBlockvorhanden ist)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}Trotz der Antworten in diesem Thread hatte ich wirklich Mühe, eine Funktion zu schreiben, die einen Block als Funktion verwendet - und zwar mit einem Parameter. Hier ist schließlich die Lösung, die ich gefunden habe.
Ich wollte eine generische Funktion schreiben loadJSONthread, die die URL eines JSON-Webdienstes verwendet, einige JSON-Daten von dieser URL in einen Hintergrundthread lädt und dann ein NSArray * der Ergebnisse an die aufrufende Funktion zurückgibt.
Grundsätzlich wollte ich die gesamte Komplexität des Hintergrund-Threads in einer generischen wiederverwendbaren Funktion verbergen.
So würde ich diese Funktion nennen:
NSString* WebServiceURL = @"http://www.inorthwind.com/Service1.svc/getAllCustomers";
[JSONHelper loadJSONthread:WebServiceURL onLoadedData:^(NSArray *results) {
// Finished loading the JSON data
NSLog(@"Loaded %lu rows.", (unsigned long)results.count);
// Iterate through our array of Company records, and create/update the records in our SQLite database
for (NSDictionary *oneCompany in results)
{
// Do something with this Company record (eg store it in our SQLite database)
}
} ];
... und das ist das Bit, mit dem ich zu kämpfen hatte: wie man es deklariert und wie man es dazu Blockbringt, die Block-Funktion aufzurufen, sobald die Daten geladen wurden, und das NSArray * der geladenen Datensätze zu übergeben:
+(void)loadJSONthread:(NSString*)urlString onLoadedData:(void (^)(NSArray*))onLoadedData
{
__block NSArray* results = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Call an external function to load the JSON data
NSDictionary * dictionary = [JSONHelper loadJSONDataFromURL:urlString];
results = [dictionary objectForKey:@"Results"];
dispatch_async(dispatch_get_main_queue(), ^{
// This code gets run on the main thread when the JSON has loaded
onLoadedData(results);
});
});
}
Diese StackOverflow-Frage betrifft das Aufrufen von Funktionen, wobei ein Block als Parameter übergeben wird. Daher habe ich den obigen Code vereinfacht und die loadJSONDataFromURLFunktion nicht eingeschlossen .
Wenn Sie interessiert sind, finden Sie eine Kopie dieser JSON-Ladefunktion in diesem Blog: http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
Hoffe das hilft einigen anderen XCode Entwicklern! (Vergessen Sie nicht, diese Frage und meine Antwort abzustimmen, wenn dies der Fall ist!)
Die vollständige Vorlage sieht aus wie
- (void) main {
//Call
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}
//Definition
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
//Execute a block
successBlock();
// failureBlock([[NSError alloc]init]);
}
- (void) successMethod {
}
- (void) failureMethod:(NSError*) error {
}