【发布时间】:2013-09-01 19:39:34
【问题描述】:
到目前为止,我已经阅读了很多关于块的信息,Apple 指南、Cocoabuilder 以及关于 SO 的 3 篇文章,并且我在代码中使用了基本上从在线教程中获得的示例。我仍在尝试理解一个具体问题。所以我决定制作一个应用程序,仅包含一个completionHandler 示例以更好地理解。这是我想出的:
视图控制器
- (void)viewDidLoad
[SantiappsHelper fetchUsersWithCompletionHandler:^(NSArray *users) {
self.usersArray = [NSMutableArray array];
for (NSDictionary *userDict in users) {
[self.usersArray addObject:[userDict objectForKey:@"username"]];
}
//WHILE TESTING postarray method, comment this out...
//[self getPoints];
[self.tableView reloadData];
}];
}
SantiappsHelper.h/m
typedef void (^Handler)(NSArray *users);
+(void)fetchUsersWithCompletionHandler:(Handler)handler {
NSString *urlString = [NSString stringWithFormat:@"http://www.myserver.com/myapp/getusers.php"];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
[request setHTTPMethod: @"GET"];
__block NSArray *usersArray = [[NSArray alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//dispatch_async(dispatch_get_main_queue(), ^{
// Peform the request
NSURLResponse *response;
NSError *error = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
// Deal with your error
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
return;
}
NSLog(@"Error %@", error);
return;
}
NSString *responseString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
usersArray = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSASCIIStringEncoding] options:0 error:nil];
if (handler){
//dispatch_sync WAITS for the block to complete before returning the value
//otherwise, the array is returned but gets zeroed out
dispatch_sync(dispatch_get_main_queue(), ^{
handler(usersArray);
});
}
});
}
这是我的理解......
我从我的 VC 中调用 fetchUsersWithCompletionHandler 并将这个完成块传递给它。该块采用 NSArray users 参数并返回 void。
同时,在 SantiappsHelper 类中,我们有一个 ^block 类型的 handler 变量,它从 VC 接收。
fetchUsersWithCompletionHandler 方法运行,采用 CompletionBlock 参数,它本身采用 NSArray users 参数?有点混乱。
webfetch 是 dispatch_async,所以它不会阻塞主线程。所以主线程上的执行继续。该新线程同步执行获取,新线程将停止直到返回响应。一旦新线程收到响应,它就会填写 NSHTTPURLResponse。返回后,它会使用 NSJSONSerialized 数据填充 usersArray。
最后它到达 if 测试并检查传入的 PARAMETER 处理程序是否存在?有点混乱……传入的参数是completionBlock。那个handler参数是不是一直存在并且明显存在,因为它被传入了?
一旦处理程序 !NULL 然后执行返回到主线程,将块期望的 NSArray 用户传回 VC 中。
但是,如果我将第二次调度更改为异步,则 usersArray 会正确填充,但是一旦将 handler(usersArray) 发送回主线程,它就会为空或为零!为什么?
【问题讨论】:
标签: objective-c objective-c-blocks