编辑:屏幕截图中突出显示的行是我遇到的问题,为什么NSURLConnection
在[NSThread main]
上运行时我没有调用它,AFNetworking
是。
我正在为我的项目使用AFNetworking,但是当在Instruments中运行Time Profiler时,我在NSURLConnection的主线程上看到很多活动,我觉得这不是我想要的。
我的方法是
- (void)parseArticles {
NSMutableArray *itemsToParse = [[FMDBDataAccess sharedDatabase] getItemsToParse];
NSMutableArray *operations = [[NSMutableArray alloc] init];
for (Post *p in itemsToParse) {
NSMutableString *strURL = [NSMutableString new];
[strURL appendString:@"http://xxxxxxxxxxxxxxxxxxxxxx.php?url="];
[strURL appendString:[p href]];
NSURL *url = [NSURL URLWithString:strURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[[ParserClient sharedInstance] registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
dispatch_async(loginParseQueue, ^{
Parser *parse = [[Parser alloc] init];
[parse parseLink:responseObject rowID:[p rowID]];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];
[operations addObject:operation];
}
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue setMaxConcurrentOperationCount:3];
[operationQueue addOperations:operations waitUntilFinished:NO];
}
为什么AFNetworking会使用主线程?以及如何解决它。
答案 0 :(得分:4)
AFNetworking正在不在主线程中的子线程上运行,但每个线程都有一个main方法,该方法位于您发布的图像上。这不是主线。现在告诉我你想修复什么?
答案 1 :(得分:4)
这是因为AFNetworking使用“successCallbackQueue”来路由完成块:
AFHTTPRequestOperation.m:
self.completionBlock = ^{
if (self.error) {
if (failure) {
dispatch_async(self.failureCallbackQueue ?: dispatch_get_main_queue(), ^{
failure(self, self.error);
});
}
} else {
if (success) {
dispatch_async(self.successCallbackQueue ?: dispatch_get_main_queue(), ^{
success(self, self.responseData);
});
}
}
};
您可以简单地为成功和失败完成块分配不同的线程:
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.name.bgqueue", NULL);
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.successCallbackQueue = backgroundQueue;
operation.failureCallbackQueue = backgroundQueue;
答案 2 :(得分:-2)
编辑:
以下是一些在后台线程中运行操作的代码。使用从UI线程调用的任何函数都将在UI线程上运行。您可以使用类似于下面指定的技术在后台线程上运行操作,然后将结果发送回UI线程供以后使用。
以下是我使用的技术,您可以使用AFHTTPRequestOperation
替换我的sendSynchronousRequest调用:
指定一种特殊类型(块),以便您可以传递代码块。
typedef void (^NetworkingBlock)(NSString* stringOut);
然后,您需要调度到后台线程,以免冻结您的UI线程。
这是一个在后台线程中调用东西,然后等待响应的函数,然后在完成时调用一个块而不使用UI线程来执行它:
- (void) sendString:(NSString*)stringIn url:(NSString*)url method:(NSString*)method completion:(NetworkingBlock)completion {
//build up a request.
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSData *postData = [stringIn dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:method];
[request setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; //or whatever
[request setHTTPBody:postData];
//dispatch a block to a background thread using GCD (grand central dispatch)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURLResponse *response;
NSError* error;
//request is sent synchronously here, but doesn't block UI thread because it is dispatched to another thread.
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//call complete, so now handle the completion block.
if (completion) {
//dispatch back to the UI thread again
dispatch_async(dispatch_get_main_queue(), ^{
if (responseData == nil) {
//no response data, so pass nil to the stringOut so you know there was an error.
completion(nil);
} else {
//response received, get the content.
NSString *content = [[NSString alloc] initWithBytes:[responseData bytes] length:responseData.length encoding:NSUTF8StringEncoding];
NSLog(@"String received: %@", content);
//call your completion handler with the result of your call.
completion(content);
}
});
}
});
}
像这样使用:
- (void) myFunction {
[self sendString:@"some text in the body" url:@"http://website.com" method:@"POST" completion:^(NSString *stringOut) {
//stringOut is the text i got back
}];
}