4

在此处输入图像描述

编辑:屏幕截图中突出显示的行是我遇到的问题,为什么在我不调用它时正在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 会使用主线程?以及我该如何解决。

4

3 回答 3

4

AFNetworking 在子线程上运行,而不是在主线程中,但每个线程都有一个 main 方法,它在您发布的图像上。这不是主线程。现在告诉我你要修复什么?

于 2013-06-04T12:52:28.017 回答
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;
于 2013-07-16T06:36:17.827 回答
-2

编辑:

这是一些在后台线程中运行操作的代码。使用从 UI 线程调用的任何函数都将在 UI 线程上运行。您可以使用类似于下面指定的技术在后台线程上运行您的操作,然后将结果分派回 UI 线程以供以后使用。

这是我使用的技术,您可以将我的 sendSynchronousRequest 调用替换为您的AFHTTPRequestOperation

指定一种特殊类型(块),以便您可以传递代码块。

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
    }];
}
于 2013-06-04T12:51:49.497 回答