NSURLConnection and grand central dispatch

后端 未结 3 371
-上瘾入骨i
-上瘾入骨i 2020-11-29 16:47

Is it advisable to wrap up NSUrlConnection in a gcd style blocks and run it on a low_priority queue?

I need to ensure that my connections are not happening on the ma

相关标签:
3条回答
  • 2020-11-29 17:23

    I recommend you to see WWDC Sessions about network application in iPhone OS.

    • WWDC 2010 Session 207 - Network Apps for iPhone OS, Part 1
    • WWDC 2010 Session 208 - Network Apps for iPhone OS, Part 2

    The lecturer said

    "Threads Are Evil™"

    for network programming and recommended to use asynchronous network programming with RunLoop. Use background thread (Grand Central Dispatch Concurrent Queue) for thread-safe data processing, not for network programming.

    By the way, Blocks and Grand Central Dispatch sessions are also worth to see.

    • WWDC 2010 Session 206 - Introducing Blocks and Grand Central Dispatch on iPhone
    • WWDC 2010 Session 211 - Simplifying iPhone App Development with Grand Central Dispatch

    I wrote a wrapper class for asynchronous NSURLConnection.


    AsyncURLConnection.h

    #import <Foundation/Foundation.h>
    
    typedef void (^completeBlock_t)(NSData *data);
    typedef void (^errorBlock_t)(NSError *error);
    
    @interface AsyncURLConnection : NSObject
    {
        NSMutableData *data_;
        completeBlock_t completeBlock_;
        errorBlock_t errorBlock_;
    }
    
    + (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
    - (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
    @end
    

    AsyncURLConnection.m

    #import "AsyncURLConnection.h"
    
    @implementation AsyncURLConnection
    
    + (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
    {
        return [[[self alloc] initWithRequest:requestUrl
            completeBlock:completeBlock errorBlock:errorBlock] autorelease];
    }
    
    - (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
    {
    
        if ((self=[super init])) {
            data_ = [[NSMutableData alloc] init];
    
            completeBlock_ = [completeBlock copy];
            errorBlock_ = [errorBlock copy];
    
            NSURL *url = [NSURL URLWithString:requestUrl];
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            [NSURLConnection connectionWithRequest:request delegate:self];
        }
    
        return self;
    }
    
    - (void)dealloc
    {
        [data_ release];
    
        [completeBlock_ release];
        [errorBlock_ release];
        [super dealloc];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        [data_ setLength:0];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [data_ appendData:data];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        completeBlock_(data_);
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        errorBlock_(error);
    }
    
    @end
    

    How to use AsyncURLConnection class.

    /*
     * AsyncURLConnection -request:completeBlock:errorBlock: have to be called
     * from Main Thread because it is required to use asynchronous API with RunLoop.
     */
    
    [AsyncURLConnection request:url completeBlock:^(NSData *data) {
    
        /* success! */
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            /* process downloaded data in Concurrent Queue */
    
            dispatch_async(dispatch_get_main_queue(), ^{
    
                /* update UI on Main Thread */
    
            });
        });
    
    } errorBlock:^(NSError *error) {
    
        /* error! */
    
    }];
    
    0 讨论(0)
  • 2020-11-29 17:41

    Have a look at this code block:

    -(void)getDataFromServer
    {
        NSDictionary *dicParams = [NSDictionary dictionaryWithObjectsAndKeys:
                               userId,    kUserID,
                               pageIndex,kPageIndex,
                               nil];
    
        NSString *yourURL = [self addQueryStringToUrlString:[NSString stringWithFormat:@"%@/%@",_PATH_,apiName] withDictionary:dicParams];
    
    
        NSString *queue_id = @"_queue_id_";
        dispatch_queue_t queue = dispatch_queue_create([queue_id UTF8String], 0);
        dispatch_queue_t main = dispatch_get_main_queue();
    
        dispatch_async(queue, ^{
    
            NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:yourURL] 
                                                        cachePolicy:NSURLRequestReloadIgnoringCacheData 
                                                    timeoutInterval:60.0];
            [theRequest setHTTPMethod:@"GET"];
            [theRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
            [theRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
            NSError        *serviceError = nil;
            NSURLResponse  *serviceResponse = nil;
            NSData *dataResponse = [NSURLConnection sendSynchronousRequest:theRequest 
                                                         returningResponse:&serviceResponse 
                                                                     error:&serviceError];
    
            if(serviceError)
            {
                dispatch_sync(main, ^{
    
                    // Update your UI
    
                    if(serviceError.code == -1012){
                        // Log error
                    }else{
                        // Log error
                    }
                });
            }
    
            else
            {
                NSError *jsonError = nil;
    
                id dataObject = [NSJSONSerialization JSONObjectWithData:dataResponse 
                                                                options:kNilOptions 
                                                                  error:&jsonError];
                NSMutableArray *arrResponse = (NSMutableArray *)dataObject;
    
                dispatch_sync(main, ^{
    
                    // Update your UI
                    [yourTableView reloadData];
                });
            }
        });
    }
    
    +(NSString*)addQueryStringToUrlString:(NSString *)urlString withDictionary:(NSDictionary *)dictionary
    {
        NSMutableString *urlWithQuerystring = [[NSMutableString alloc] initWithString:urlString];
    
        for (id key in dictionary) {
            NSString *keyString = [key description];
            NSString *valueString = [[dictionary objectForKey:key] description];
    
            if ([urlWithQuerystring rangeOfString:@"?"].location == NSNotFound) {
                [urlWithQuerystring appendFormat:@"?%@=%@", [self urlEscapeString:keyString], [self urlEscapeString:valueString]];
            } else {
                [urlWithQuerystring appendFormat:@"&%@=%@", [self urlEscapeString:keyString], [self urlEscapeString:valueString]];
            }
        }
        return urlWithQuerystring;
    }
    
    +(NSString*)urlEscapeString:(NSString *)unencodedString
    {
        CFStringRef originalStringRef = (__bridge_retained CFStringRef)unencodedString;
        NSString *s = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,originalStringRef, NULL, NULL,kCFStringEncodingUTF8);
        CFRelease(originalStringRef);
        return s;
    }
    
    0 讨论(0)
  • Create a concurrent NSOperation on which you run your asynchronous NSURLConnection.

    0 讨论(0)
提交回复
热议问题