异步请求 运行 慢 - iOS
Asynchronous request running slowly - iOS
我有一个应用程序可以从服务器下载一组照片。我正在使用异步请求,因为我不想 UI 被阻止。但是,我发现请求非常慢并且需要很长时间才能加载。
我知道您可以将队列类型设置为 [NSOperationQueue mainQueue]
但这只会将异步请求放回主线程,这破坏了首先发出异步请求的全部意义。
有没有办法加快请求速度或者告诉iOS:"Run this request in the background, but do it ASAP, don't leave it till the end of the queue"???
这是我的代码:
// Set up the photo request.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:PHOTO_URL, pass_venue_ID, PHOTO_CLIENT_ID, PHOTO_CLIENT_SECRET]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// Begin the asynchromous image loading.
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error == nil) {
// Convert the response data to JSON.
NSError *my_error = nil;
NSDictionary *feed = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&my_error];
// Check to see if any images exist
// for this particular place.
int images_check = [[NSString stringWithFormat:@"%@", [[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"count"]] intValue];
if (images_check > 0) {
// Download all the image link properties.
images_prefix = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"prefix"];
images_suffix = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"suffix"];
images_width = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"width"];
images_height = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"height"];
// Set the image number label.
number_label.text = [NSString stringWithFormat:@"1/%lu", (unsigned long)[images_prefix count]];
// Download up to 5 images.
images_downloaded = [[NSMutableArray alloc] init];
// Set the download limit.
loop_max = 0;
if ([images_prefix count] > 5) {
loop_max = 5;
}
else {
loop_max = [images_prefix count];
}
for (NSUInteger loop = 0; loop < loop_max; loop++) {
// Create the image URL.
NSString *image_URL = [NSString stringWithFormat:@"%@%@x%@%@", images_prefix[loop], images_width[loop], images_height[loop], images_suffix[loop]];
// Download the image file.
NSData *image_data = [NSData dataWithContentsOfURL:[NSURL URLWithString:image_URL]];
// Store the image data in the array.
[images_downloaded addObject:image_data];
}
// Load the first image.
[self load_image:image_num];
}
else if (images_check <= 0) {
// error...
}
}
else {
// error
}
}];
丹,谢谢你的时间。
我认为你的问题不是请求 运行 慢,而是你正在更新不在主线程上的 UI 元素,包围任何 UI 更新(比如将文本设置为标签)与
dispatch_sync(dispatch_get_main_queue(), ^{
<#code#>
});
正如 Fonix 所说,这并不是 iOS 响应缓慢,而是 dataWithContentsOfURL 在后台线程中不起作用。 Apple 的建议是您应该将 NSURLConnection 与委托异步使用
- didReceiveResponse
- didReceiveData
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:theURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:_mAuthenticationTimeoutInterval];
在这些方法中,您也可以使用数据块。
如果您确实希望这些多个下载更快,您应该使用 NSOperationQueue 并行下载。可以参考enter link description here
我认为一个好的解决方案可能是将 AFNetworking 与 NSOperation 结合使用,检查我编写的这段代码以异步执行多个操作
NSMutableArray *operations = [[NSMutableArray alloc] init];
for(NSObject *obj in caches) {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
//...set up your mutable request options here
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
if(statusCode==200) {
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"API Call error:%@", error.localizedDescription);
}];
[[requestManager operationQueue] addOperation:operation];
[operations addObject:operation];
if([operations count] >= MAX_API_CALL) break;
}
[AFHTTPRequestOperation batchOfRequestOperations:operations progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
} completionBlock:^(NSArray *operations) {
NSError *error;
for (AFHTTPRequestOperation *op in operations) {
if (op.isCancelled){
}
if (op.responseObject){
// process your responce here
}
if (op.error){
error = op.error;
}
}
}];
我有一个应用程序可以从服务器下载一组照片。我正在使用异步请求,因为我不想 UI 被阻止。但是,我发现请求非常慢并且需要很长时间才能加载。
我知道您可以将队列类型设置为 [NSOperationQueue mainQueue]
但这只会将异步请求放回主线程,这破坏了首先发出异步请求的全部意义。
有没有办法加快请求速度或者告诉iOS:"Run this request in the background, but do it ASAP, don't leave it till the end of the queue"???
这是我的代码:
// Set up the photo request.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:PHOTO_URL, pass_venue_ID, PHOTO_CLIENT_ID, PHOTO_CLIENT_SECRET]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// Begin the asynchromous image loading.
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error == nil) {
// Convert the response data to JSON.
NSError *my_error = nil;
NSDictionary *feed = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&my_error];
// Check to see if any images exist
// for this particular place.
int images_check = [[NSString stringWithFormat:@"%@", [[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"count"]] intValue];
if (images_check > 0) {
// Download all the image link properties.
images_prefix = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"prefix"];
images_suffix = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"suffix"];
images_width = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"width"];
images_height = [[[[feed objectForKey:@"response"] valueForKey:@"photos"] valueForKey:@"items"] valueForKey:@"height"];
// Set the image number label.
number_label.text = [NSString stringWithFormat:@"1/%lu", (unsigned long)[images_prefix count]];
// Download up to 5 images.
images_downloaded = [[NSMutableArray alloc] init];
// Set the download limit.
loop_max = 0;
if ([images_prefix count] > 5) {
loop_max = 5;
}
else {
loop_max = [images_prefix count];
}
for (NSUInteger loop = 0; loop < loop_max; loop++) {
// Create the image URL.
NSString *image_URL = [NSString stringWithFormat:@"%@%@x%@%@", images_prefix[loop], images_width[loop], images_height[loop], images_suffix[loop]];
// Download the image file.
NSData *image_data = [NSData dataWithContentsOfURL:[NSURL URLWithString:image_URL]];
// Store the image data in the array.
[images_downloaded addObject:image_data];
}
// Load the first image.
[self load_image:image_num];
}
else if (images_check <= 0) {
// error...
}
}
else {
// error
}
}];
丹,谢谢你的时间。
我认为你的问题不是请求 运行 慢,而是你正在更新不在主线程上的 UI 元素,包围任何 UI 更新(比如将文本设置为标签)与
dispatch_sync(dispatch_get_main_queue(), ^{
<#code#>
});
正如 Fonix 所说,这并不是 iOS 响应缓慢,而是 dataWithContentsOfURL 在后台线程中不起作用。 Apple 的建议是您应该将 NSURLConnection 与委托异步使用 - didReceiveResponse - didReceiveData
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:theURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:_mAuthenticationTimeoutInterval];
在这些方法中,您也可以使用数据块。
如果您确实希望这些多个下载更快,您应该使用 NSOperationQueue 并行下载。可以参考enter link description here
我认为一个好的解决方案可能是将 AFNetworking 与 NSOperation 结合使用,检查我编写的这段代码以异步执行多个操作
NSMutableArray *operations = [[NSMutableArray alloc] init];
for(NSObject *obj in caches) {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
//...set up your mutable request options here
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
if(statusCode==200) {
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"API Call error:%@", error.localizedDescription);
}];
[[requestManager operationQueue] addOperation:operation];
[operations addObject:operation];
if([operations count] >= MAX_API_CALL) break;
}
[AFHTTPRequestOperation batchOfRequestOperations:operations progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
} completionBlock:^(NSArray *operations) {
NSError *error;
for (AFHTTPRequestOperation *op in operations) {
if (op.isCancelled){
}
if (op.responseObject){
// process your responce here
}
if (op.error){
error = op.error;
}
}
}];