본문 바로가기

Program/iOS

[iOS] 비동기 네트워크 쓰래드 - NetworkThread

** 개인적 메모입니다. 태클 사절 **

비동기 네트워크 쓰래드

  • NetworkThread.h
     
    //
    //  NetworkThread.h
    //
    //  Created by yungduk jung on 12. 5. 14..
    //  Copyright (c) 2012년 __MyCompanyName__. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    #define REQ_METHOD_POST  @"POST"
    #define REQ_METHOD_GET    @"GET"
    
    #define RES_NET_RESULT                          @"RES_NET_RESULT"
    #define RES_NET_ERROR                            @"RES_NET_ERROR"
    #define RES_OBJECT_DICTIONARY_KEY       @"RES_OBJECT_DICTIONARY_KEY"
    #define RES_TRANSFER_DICTIONARY_KEY   @"RES_TRANSFER_DICTIONARY_KEY"
    
    #define DEFAULT_TIMEOUT_INTERVAL 20
    
    @interface NetworkThread : NSObject {
    @private    
        NSMutableDictionary* objectDictionary;
        void* blockHandler;
    }
    
    @property(nonatomic, retain) id target;
    @property(nonatomic, retain) NSString *url;
    @property(nonatomic, assign) SEL selector;
    @property(nonatomic, retain) NSData *requestData;
    @property(nonatomic, retain) NSObject *transferObject;
    @property(nonatomic, assign) NSTimeInterval timeInterval;
    @property(nonatomic, retain) NSString *reqMethod;
    @property(nonatomic, assign) BOOL waitUntil;
    @property(nonatomic, assign) BOOL isLoing;
    
    -(void)setBlockHandler:(void*)block;
    -(void)start;
    
    @end
    
  • NetworkThread.m
     
    //
    //  NetworkThread.m
    //
    //  Created by yungduk jung on 12. 5. 14..
    //  Copyright (c) 2012년 __MyCompanyName__. All rights reserved.
    //
    
    #import "NetworkThread.h"
    #import "NetUtil.h"
    
    #define HTTP_OK 200
    
    @implementation NetworkThread
    
    @synthesize target;
    @synthesize url;
    @synthesize selector;
    @synthesize requestData;
    @synthesize transferObject;
    @synthesize timeInterval;
    @synthesize reqMethod;
    @synthesize waitUntil;
    
    @synthesize isLoing;
    
    -(id)init {
        
        self = [super init];
        objectDictionary = [[NSMutableDictionary alloc] init];
        reqMethod = REQ_METHOD_GET;
        timeInterval = DEFAULT_TIMEOUT_INTERVAL;
        isLoing = NO;
        
        NSLog(@"blockHandler = %@", blockHandler);
        
        return self;
    }
    
    -(void)setWaitUtil:(BOOL)wait {
        waitUntil = wait;
    }
    
    -(void)setTimeOutInterval:(NSTimeInterval)seconds {
        timeInterval = seconds;
    }
    
    -(void)setReqMethod:(NSString*)requestMethod {
        reqMethod = requestMethod;
    }
    
    -(void)setBlockHandler:(void*)block {
        NSLog(@"block = %@", block);
        blockHandler = (void *)[(void (^)(void))block copy];    
        NSLog(@"blockHandler = %@", blockHandler);
    }
    
    -(void)start {
        if( isLoing ) {
            NSLog(@"NETWORKTHREAD START     = %@", self);
        }
        [NSThread detachNewThreadSelector:@selector(reqeust) toTarget:self withObject:nil];
    }
    
    -(void)reqeust {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        
        if( [NetUtil alertIsNetworkEnable] ) {
            NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
            
            if( isLoing ) {
                NSLog(@"REQEUST TARGET          = %@, %@", self, target);
                NSLog(@"REQEUST SELECTOR        = %@, %@", self, NSStringFromSelector(selector));
                NSLog(@"REQUEST URL             = %@, %@", self, url);
                NSLog(@"REQUEST URL ENCODING    = %@, %@", self, [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]);
                NSLog(@"REQUEST METHOD          = %@, %@", self, reqMethod);
                NSLog(@"REQUEST TIME INTERVAL   = %@, %f", self, timeInterval);
                
            }
            
            if( [reqMethod isEqualToString:REQ_METHOD_POST] ) {
                // POST
                if( requestData != nil ) {
                    [request setHTTPBody:requestData];
                    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
                }
    
                if( isLoing ) {
                    NSLog(@"REQUEST POST DATA       = %@, %@", self, [[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding]);
                }
            }
            
            [request setURL:[NSURL URLWithString:[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
            [request setHTTPMethod:reqMethod];
            [request setTimeoutInterval:timeInterval];
            
            NSError* error= nil;
            NSURLResponse* response = nil;        
            NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
            
            if( isLoing ) {
                //NSLog(@"REQUEST RESPONSE DATA   = %@, %@", self, data);
                NSLog(@"REQUEST RESPONSE ERROR  = %@, %@", self, error);
                NSLog(@"REQUEST RESPONSE STATUS = %@, %d", self, [(NSHTTPURLResponse *)response statusCode]);
            }
            
            if( [(NSHTTPURLResponse *)response statusCode] == HTTP_OK ) {
                NSString* dataString = nil;
                
                if( data != nil ) {
                    [objectDictionary setObject:@"Y" forKey:RES_NET_RESULT];
                    dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                    [objectDictionary setObject:dataString forKey:RES_OBJECT_DICTIONARY_KEY];
                    [dataString release];
                }
                
                if( transferObject != nil ) {
                    [objectDictionary setObject:transferObject forKey:RES_TRANSFER_DICTIONARY_KEY];
                }
                
                
            } else {
                [objectDictionary setObject:@"N" forKey:RES_NET_RESULT];
                
                //2012.06.08 리뷰 신청 후 버그 발견.. HTTP_OK 가 아닌데 error 값이 없는 경우가 있다.
                if( error != nil ) {
                    [objectDictionary setObject:error forKey:RES_NET_ERROR];
                }
            }
            
            if( isLoing ) {
                NSLog(@"REQUEST RESPONSE CALL = %@, %@", self, NSStringFromSelector(selector));
                //NSLog(@"REQUEST RESPONSE OBJECT = %@, %@", self, objectDictionary); 
            }
            
            if( target != nil ) {
                [target performSelectorOnMainThread:selector withObject:objectDictionary waitUntilDone:waitUntil];
            }
            
            /** 블럭 핸들러 처리 */
            if( blockHandler != nil ){
                ((void (^)(id arg1))blockHandler)(objectDictionary);
            }
            
            [request release];
            
            [self release];
        }
        
        [pool release];
    }
    
    -(void)dealloc {
        if( isLoing ) {
            NSLog(@"NETWORK THREAD DEALLOC");
        }
        
        [target release];
        [url release];
        [requestData release];
        [transferObject release];
        [reqMethod release];
        [objectDictionary release];
        
        [(void (^)(void))blockHandler release];
    
        [super dealloc];
    }
    
    @end
    
  • 사용예... selector 와 block handler 모두 response call event

     
     NetworkThread *networkThread = [[NetworkThread alloc] init];
     [networkThread setUrl:@"http://0.0.0.0/smart/ios/index.asp"];
     [networkThread setIsLoing:YES];
     [networkThread setTarget:self];
     [networkThread setSelector:@selector(netResIndexAsp:)];
     [networkThread setBlockHandler:^(NSMutableDictionary* obj){
            NSLog(@"BLOCK CODE CALL..");
            NSLog(@"obj = %@", obj);
            NSLog(@"RES_NET_RESULT = %@", [obj objectForKey:RES_NET_RESULT]);
            
            NSLog(@"self = %@", self);
            
            dispatch_sync(dispatch_get_main_queue(), ^{
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"AlertView"
                                                                    message:@"alertview in block code"
                                                                   delegate:self
                                                          cancelButtonTitle:@"확인"
                                                          otherButtonTitles:@"아니오", nil];
                [alertView show];
                [alertView release];
         });
     }];    
        [networkThread start];
    
  • [networkThread setSelector:@selector(netResIndexAsp:)]; 로 처리되는 경우...

     
    -(void)netResIndexAsp:(NSMutableDictionary*)obj {
        NSLog(@"obj = %@", obj);
        NSLog(@"RES_NET_RESULT = %@", [obj objectForKey:RES_NET_RESULT]);
    }