gpt4 book ai didi

iphone - NSURLConnection 发送异步请求 : Blocking Main Thread

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:10:29 25 4
gpt4 key购买 nike

我正在使用 NSURLConnection 发出多个异步请求。我想显示一个进度指示器,以显示要执行的总数中已完成的请求数。但是,当我尝试在发出请求之前或在执行请求之前调用的另一个方法中设置和显示此进度指示器时,它不会显示。当请求被注释掉时,进度指示器显示正常。但如果不是,就好像 Xcode 向前看并看到异步请求到来并阻塞主线程,从而使 UI 更改变得不可能。

下面是被调用的相关代码,包括请求和显示进度指示器的代码:

- (void)getRegionalInformationFromChecked:(NSSet *)set atIndex:(NSInteger)index {
__block BOOL responseRecieved = NO;
NSString *stringForURL = [NSString stringWithFormat:@"http://www.thebluealliance.com/api/v1/event/details?event=%@",[[set allObjects] objectAtIndex:index]];
NSURL *url = [NSURL URLWithString:stringForURL];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSLog(@"URL IS GO: %@", stringForURL);
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:queue completionHandler:^(NSURLResponse *_response, NSData *_data, NSError *_error) {
NSLog(@"CHECKED DATA RETURNED AT INDEX %i", index);
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:_data options:NSJSONReadingMutableContainers error:&error];
if (!_regionalDetails) {
_regionalDetails = [[NSMutableArray alloc] init];
}
[_regionalDetails addObject:dict];
responseRecieved = YES;
}];
regionalSchedulesToGet = [set count];
while (responseRecieved == NO) {}
[[MBProgressHUD HUDForView:[[UIApplication sharedApplication] keyWindow]] setLabelText:[NSString stringWithFormat: @"Getting regional %i of %i", index+2, [set count]]];
if (index+1 < [set count]) {
[self getRegionalInformationFromChecked:set atIndex:index+1];
} else {
[[MBProgressHUD HUDForView:[[UIApplication sharedApplication] keyWindow]] setLabelText:@"Writing to file"];
}
}

当异步请求的 block 被注释掉时,MBProgressHUD 会正常显示它的值。但是当 block 被插入时,SDK 拒绝更新进度指示器,即使在离开 block 之后(之后任何线程问题应该已经解决)。它不会更新,直到没有更多的显示请求,此时它会显示“正在写入文件”。

为什么异步请求似乎阻塞了主线程,为什么我不能在调用请求之前或之后立即在主线程上进行更改?

最佳答案

while (responseRecieved == NO) {}

您阻塞主线程(可能 CPU 负载几乎为 100%),直到异步 block 完成。然后你调用你的递归函数,启动另一个异步 block 并再次阻塞,直到完成的。因此,程序控制不会返回到主运行循环,直到all操作已经完成。只有这样,UI 更新才会完成。

而不是同步等待(这总是一个坏主意),你应该在完成 block 的末尾开始下一个操作。

还要注意 sendAsynchronousRequestqueue 参数是队列调用完成处理程序,因此您可以只使用 [NSOperationQueue mainQueue]

那么你的代码大概是这样的:

- (void)getRegionalInformationFromChecked:(NSSet *)set atIndex:(NSInteger)index
{
[[MBProgressHUD HUDForView:[[UIApplication sharedApplication] keyWindow]]
setLabelText:[NSString stringWithFormat:@"Getting regional %i of %i", index+1, [set count]]];
NSString *stringForURL = [NSString stringWithFormat:@"http://www.thebluealliance.com/api/v1/event/details?event=%@",[[set allObjects] objectAtIndex:index]];
NSURL *url = [NSURL URLWithString:stringForURL];
NSLog(@"URL IS GO: %@", stringForURL);
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *_response, NSData *_data, NSError *_error) {
NSLog(@"CHECKED DATA RETURNED AT INDEX %i", index);
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:_data options:NSJSONReadingMutableContainers error:&error];
if (!_regionalDetails) {
_regionalDetails = [[NSMutableArray alloc] init];
}
[_regionalDetails addObject:dict];
if (index+1 < [set count]) {
[self getRegionalInformationFromChecked:set atIndex:index+1];
} else {
[[MBProgressHUD HUDForView:[[UIApplication sharedApplication] keyWindow]] setLabelText:@"Writing to file"];
// ... perhaps call a completion function from here ?
}
}];
}

但请注意,对 getRegionalInformationFromChecked 的初始调用现在将几乎立即返回(这就是异步任务的工作方式:-)。

关于iphone - NSURLConnection 发送异步请求 : Blocking Main Thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16124369/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com