简体   繁体   中英

AFNetworking and NSURLConnection on main thread

在此处输入图片说明

EDIT: The highlighted row in the screenshot is what I have a problem with, why is NSURLConnection running on [NSThread main] when I'm not calling it, AFNetworking is.

I'm using AFNetworking for my project, but when running Time Profiler in Instruments I'm seeing a lot of activity on the main thread for NSURLConnection, I have a feeling this is not what I want.

My method is

- (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];
}

Why would AFNetworking be using the main thread? and how do I fix it.

AFNetworking is running on a child thread not in main thread, but every thread has a main method, which is on the image you post. This is not the main thread.Now tell me What do you want to fix?

It's because AFNetworking uses "successCallbackQueue" to route the completion block :

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);
            });
        }
    }
};

You can simply assign a different thread to success and failure completion blocks :

dispatch_queue_t backgroundQueue = dispatch_queue_create("com.name.bgqueue", NULL);
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.successCallbackQueue = backgroundQueue;
operation.failureCallbackQueue = backgroundQueue;

EDIT:

Here is some code to run operations in a background thread. Use of any function called from the UI thread will run on on the UI thread. You can use a technique similar to the one specified below to run your operation on a background thread, and then dispatch the result back to the UI thread for later use.

Here is the technique I used, you may replace my sendSynchronousRequest call with your AFHTTPRequestOperation :

Specify a special type (a block) so you can pass blocks of code around.

typedef void (^NetworkingBlock)(NSString* stringOut);

Then, you need to dispatch to a background thread, so as not to freeze your UI thread.

Here's a function to call stuff in a background thread, and then wait for a response, and then call a block when done without using the UI thread to do it:

- (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);
                }
            });
        }
    });
}

Use it like this:

- (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
    }];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM