由调用者提供要由方法(块的主体)运行的代码。调用该代码取决于实现者。
从一个简单的例子开始,假设调用者只是想让你用 urlString 形成一个数组并回调,那么你可以这样做:
- (void)downloadedDataURLString:(NSString *)urlString
completionHandler:(void (^)(NSArray *, NSError *))completionHandler {
NSArray *callBackWithThis = @[urlString, @"Look ma, no hands"];
completionHandler(callBackWithThis, nil);
}
调用者会这样做:
- (void)someMethodInTheSameClass {
// make an array
[self downloadedDataURLString:@"put me in an array"
completionHandler:^(NSArray *array, NSError *error) {
NSLog(@"called back with %@", array);
}];
}
调用者将使用@“把我放入一个数组”和@“看,妈妈,没有手”来记录一个包含两项的数组。在一个更现实的例子中,假设有人要求您在完成下载后给他们回电:
- (void)downloadedDataURLString:(NSString *)urlString
completionHandler:(void (^)(NSArray *, NSError *))completionHandler {
// imagine your caller wants you to do a GET from a web api
// stripped down, that would look like this
// build a request
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// run it asynch
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error) {
// imagine that the api answers a JSON array. parse it
NSError *parseError;
id parse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&parseError];
// here's the part you care about: the completionHandler can be called like a function. the code the caller supplies will be run
if (!parseError) {
completionHandler(parse, nil);
} else {
NSLog(@"json parse error, error is %@", parseError);
completionHandler(nil, parseError);
}
} else {
NSLog(@"error making request %@", error);
completionHandler(nil, error);
}
}];
// remember, this launches the request and returns right away
// you are calling the block later, after the request has finished
}