我按照教程和我输入的方法如下:
+(void)downlaodDataFromURL:(NSURL *)url withCompletionHandler:(void (^)(NSData *))completionHandler{
// Instantiate a session configuration object
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// Instantiate a session object
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
// Create a data task object to perform the data downloading
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil){
// If any error occurs then just display its description on the console
NSLog(@" %@", [error localizedDescription]);
}
else {
//If no errors occurs, check the HTTP status code.
NSInteger HTTPStatusCode = [(NSHTTPURLResponse*)response statusCode];
//If it's other than 200, then show it on console.
if (HTTPStatusCode != 200){
NSLog(@"HTTP status code = %d", HTTPStatusCode);
}
//Call the completion handler with the returned data on the main thread.
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
completionHandler (data);
completionHandler (data);
}];
}
}];
//Resume the task
[task resume];
}
我有两个问题:
首先 - 在方法声明中,我见过以下:withCompletionHandler:(void (^)(NSData *))completionHandler
。我从未见过像(void (^)
那样的建筑。在我对方法语法的理解中,我们有参数和类型,该方法应该返回或不返回,但那是什么?我从未见过void
这样的地方,(^)
是什么?我知道,^
意味着阻止,但那个结构怎么样?
第二 - 在
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
completionHandler (data);
}];
我看到completionHandler (data);
。有圆括号,completionHandler
在top方法中声明,数据显而易见,我们从URL获取数据。但究竟是什么以及什么是 - completionHandler?当我查看(void (^)(NSData *))completionHandler
时,我认为completionHandler
是NSData
类型的对象。这对我来说毫无意义。我猜,我只是无法正确理解语法。
请你解释一下吗?我知道这个的全部含义,但是这两段代码让我感到困惑..谢谢!
编辑:
在我的viewController.m中,我有一个声明如下的方法:
-(void)getCountryInfo{
//Prepare the URL that we'll get the country info data from.
NSString *URLString = [NSString stringWithFormat:@"http://api.geonames.org/countryInfoJSON?username=Necrosoft&country=%@", self.countryCode];
NSURL *url = [NSURL URLWithString:URLString];
[AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data){
//Check if any data returned
if (data != nil){
//Convert the returned data into a dictionary
NSError *error;
NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error != nil){
NSLog(@"%@", [error localizedDescription]);
}
else {
self.countryDetailsDictionary = [[returnedDict objectForKey:@"geonames"] objectAtIndex:0];
NSLog(@"%@", self.countryDetailsDictionary);
//Set the country name to the respective label.
self.lblCountry.text = [NSString stringWithFormat:@" %@ (%@)", [self.countryDetailsDictionary objectForKey:@"countryName"], [self.countryDetailsDictionary objectForKey:@"countryCode"]];
//Reload the table view.
[self.tblCountryDetails reloadData];
//Show the table view.
self.tblCountryDetails.hidden = NO;
}
}
}];
}
上面描述了一个类方法调用:
[AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data){
...// there is code pasted above
所以,如果我理解正确,completionHandler (data);
调用定义如下:
//Check if any data returned
if (data != nil){
//Convert the returned data into a dictionary
NSError *error;
NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error != nil){
NSLog(@"%@", [error localizedDescription]);
}
else {
self.countryDetailsDictionary = [[returnedDict objectForKey:@"geonames"] objectAtIndex:0];
NSLog(@"%@", self.countryDetailsDictionary);
//Set the country name to the respective label.
self.lblCountry.text = [NSString stringWithFormat:@" %@ (%@)", [self.countryDetailsDictionary objectForKey:@"countryName"], [self.countryDetailsDictionary objectForKey:@"countryCode"]];
//Reload the table view.
[self.tblCountryDetails reloadData];
//Show the table view.
self.tblCountryDetails.hidden = NO;
当data是我们成功下载的NSData对象时:
AppDelegate downlaodDataFromURL:url withCompletionHandler:^(NSData *data)
我是对的吗?
答案 0 :(得分:1)
withCompletionHandler:(void (^)(NSData *))completionHandler
Objective-C方法使用C类型转换语法声明参数。所以,这可以被认为是:
withCompletionHandler:(SomeType)completionHandler
其中 SomeType 为void (^)(NSData *)
。诚然,这是一种丑陋而混乱的语法。这意味着:阻止一个块的指针,该块接受一个NSData*
参数并且不返回任何内容(返回void
)。
考虑:
void foo(NSData *);
这显然是一个函数的声明,它接受NSData*
参数并且不会返回任何内容。
下一步:
void (^foo)(NSData *);
这是一个名为foo
的块变量的声明,它接受NSData*
参数并且不会返回任何内容。
现在,要将其设为一个类型,请删除名称foo
:
void (^)(NSData *)
这是我上一个示例中foo
的类型和代码中的completionHandler
参数。
希望这有助于回答您的第二个问题。代码:
completionHandler (data);
是completionHandler
块的调用。它将data
作为参数传递给块,该块与块的已知类型匹配。