Objective-C:等待执行'While'循环直到NSURLConnection请求完成
Objective-C: Wait to execute 'While' loop until NSURLConnection request is complete
基本上我想要一种在循环中多次发出 NSURLRequest 直到满足特定条件的方法。我正在使用 rest api 但 rest api 一次最多只允许 1,000 个结果。因此,如果我总共有 1,500 个,我想请求获得前 1,000 个,然后我需要用另一个几乎完全相同的请求来获得其余部分,除了 startAt: 参数不同(所以我可以从 1001 - 1500 。我想在一个 while 循环中设置它(当我完成加载所有数据时)并且我只是在阅读信号量但它没有像我预期的那样工作。我不知道我有多少结果,直到我提出第一个请求。它可以是 50、1000 或 10,000。
代码如下:
while(!finishedLoadingAllData){
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLRequest *myRequest = [self loadData: startAt:startAt maxResults:maxResults];
[NSURLConnection sendAsynchronousRequest:myRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if(error){
completionHandler(issuesWithProjectData, error);
}
else{
NSDictionary *issuesDictionary = [[NSDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]];
[issuesWithProjectData addObjectsFromArray:issuesDictionary[@"issues"]];
if(issuesWithProjectData.count == [issuesDictionary[@"total"] integerValue]){
completionHandler([issuesWithProjectData copy], error);
finishedLoadingAllData = YES;
}
else{
startAt = maxResults + 1;
maxResults = maxResults + 1000;
}
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
基本上我想让 while 循环一直等到完成块完成。然后我才希望 while 循环检查我们是否拥有所有数据(如果没有,请使用更新的 startAt value/maxResults 值发出另一个请求。
现在它只是挂在 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
我做错了什么或者我需要做什么?也许信号量是错误的解决方案。谢谢。
好的。我看得越多,我就越不认为用信号量来解决这个问题是个坏主意,因为另一种方法是使用串行队列等,而且这个解决方案并没有那么复杂。
问题是,您要求完成处理程序在主线程
上 运行
[NSURLConnection sendAsynchronousRequest:myRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
您可能正在主线程中创建 NSURL 请求。因此,当它等待信号量在主线程上被释放时,NSURL 完成处理程序正在等待主线程从其当前的 运行 循环中解脱出来。
所以创建一个新的操作队列。
做这样的事情不是更容易吗:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //run on a background thread
while(!finishedLoadingAllData){
NSURLRequest *myRequest = [self loadData: startAt:startAt maxResults:maxResults];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:myRequest returningResponse:&response error:&error]; //blocks until completed
if(response.statusCode == 200 && responseData != nil){ //handle response and set finishedLoadingAllData when you want
//do stuff with response
dispatch_sync(dispatch_get_main_queue(), ^{
//do stuff on the main thread that needs to be done
}
}
});
请不要那样做..NSURLConnection sendAsynchronousRequest
将为您循环加载自身,如果您的数据是大块的..试试这个..
__block NSMutableData *fragmentData = [NSMutableData data];
[[NSOperationQueue mainQueue] cancelAllOperations];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
[fragmentData appendData:data];
if ([data length] == 0 && error == nil)
{
NSLog(@"No response from server");
}
else if (error != nil && error.code == NSURLErrorTimedOut)
{
NSLog(@"Request time out");
}
else if (error != nil)
{
NSLog(@"Unexpected error occur: %@", error.localizedDescription);
}
else if ([data length] > 0 && error == nil)
{
if ([fragmentData length] == [response expectedContentLength])
{
// finished loading all your data
}
}
}];
我创建了两个来自服务器处理方法的大块 json 响应。其中之一就是这个,所以希望这对您也有用。干杯! ;)
基本上我想要一种在循环中多次发出 NSURLRequest 直到满足特定条件的方法。我正在使用 rest api 但 rest api 一次最多只允许 1,000 个结果。因此,如果我总共有 1,500 个,我想请求获得前 1,000 个,然后我需要用另一个几乎完全相同的请求来获得其余部分,除了 startAt: 参数不同(所以我可以从 1001 - 1500 。我想在一个 while 循环中设置它(当我完成加载所有数据时)并且我只是在阅读信号量但它没有像我预期的那样工作。我不知道我有多少结果,直到我提出第一个请求。它可以是 50、1000 或 10,000。
代码如下:
while(!finishedLoadingAllData){
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLRequest *myRequest = [self loadData: startAt:startAt maxResults:maxResults];
[NSURLConnection sendAsynchronousRequest:myRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if(error){
completionHandler(issuesWithProjectData, error);
}
else{
NSDictionary *issuesDictionary = [[NSDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]];
[issuesWithProjectData addObjectsFromArray:issuesDictionary[@"issues"]];
if(issuesWithProjectData.count == [issuesDictionary[@"total"] integerValue]){
completionHandler([issuesWithProjectData copy], error);
finishedLoadingAllData = YES;
}
else{
startAt = maxResults + 1;
maxResults = maxResults + 1000;
}
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
基本上我想让 while 循环一直等到完成块完成。然后我才希望 while 循环检查我们是否拥有所有数据(如果没有,请使用更新的 startAt value/maxResults 值发出另一个请求。
现在它只是挂在 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
我做错了什么或者我需要做什么?也许信号量是错误的解决方案。谢谢。
好的。我看得越多,我就越不认为用信号量来解决这个问题是个坏主意,因为另一种方法是使用串行队列等,而且这个解决方案并没有那么复杂。
问题是,您要求完成处理程序在主线程
[NSURLConnection sendAsynchronousRequest:myRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
您可能正在主线程中创建 NSURL 请求。因此,当它等待信号量在主线程上被释放时,NSURL 完成处理程序正在等待主线程从其当前的 运行 循环中解脱出来。
所以创建一个新的操作队列。
做这样的事情不是更容易吗:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //run on a background thread
while(!finishedLoadingAllData){
NSURLRequest *myRequest = [self loadData: startAt:startAt maxResults:maxResults];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:myRequest returningResponse:&response error:&error]; //blocks until completed
if(response.statusCode == 200 && responseData != nil){ //handle response and set finishedLoadingAllData when you want
//do stuff with response
dispatch_sync(dispatch_get_main_queue(), ^{
//do stuff on the main thread that needs to be done
}
}
});
请不要那样做..NSURLConnection sendAsynchronousRequest
将为您循环加载自身,如果您的数据是大块的..试试这个..
__block NSMutableData *fragmentData = [NSMutableData data];
[[NSOperationQueue mainQueue] cancelAllOperations];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
[fragmentData appendData:data];
if ([data length] == 0 && error == nil)
{
NSLog(@"No response from server");
}
else if (error != nil && error.code == NSURLErrorTimedOut)
{
NSLog(@"Request time out");
}
else if (error != nil)
{
NSLog(@"Unexpected error occur: %@", error.localizedDescription);
}
else if ([data length] > 0 && error == nil)
{
if ([fragmentData length] == [response expectedContentLength])
{
// finished loading all your data
}
}
}];
我创建了两个来自服务器处理方法的大块 json 响应。其中之一就是这个,所以希望这对您也有用。干杯! ;)