본문 바로가기
아이폰 개발/ios 개념&튜토리얼

IOS NSURLSession으로 Get 요청 Post 요청 - 구현

by 인생여희 2020. 12. 3.

 

 

지난 시간에는 NSURLSession을 언제사용하고 왜사용하는지, 그리고 NSURLSession이 어떻게 생긴녀석인지에 대해서 알아보는

시간을 가졌다. NSURLSession을 구현하기 전에 NSURLSession에 대한 개념을 잡고오면 코드로 구현하는데 도움이 될거라고 생각한다.

 

🔅IOS NSURLSession으로 Get 요청 Post 요청 - 개념

 

 

🔅미리보기

이번시간에 코드로 구현할 내용은 아래와 같다. 아래 그림처럼 get 버튼을 누르면 get 방식으로 url을 호출해서 데이터를 얻어와서 화면에 뿌려줄 것이고, post 요청 버튼을 누르면 post 요청으로 데이터를 받아와서 화면에 뿌려줄 것이다. 그리고 새창열기는 비슷한데, 델리게이트 메소드들이 호출되는 방식으로 구현을 해놓았다.

 

 

🔅화면 디자인

화면은 네비게이션 뷰컨트롤러를 사용해서 새창열기 버튼을 누르면 새창이 열리는 형태로 만들었다. 전체적인 스토리 보드는 아래와 같다.

 

🔅NSURLSessionDataDelegate 구현

먼저 interface에 NSURLSessionDataDelegate을 구현해준다.

@interface ViewController : UIViewController <NSURLSessionDataDelegate>

 

🔅Get 방식으로 호출

먼저 Get방식으로 요청하는 코드를 살펴보자. 소스에 대한 설명은 주석으로 달아 놓았다. 요청 URL은 더미 json data api를 온라인으로 제공해주는 https://reqres.in/api/users/2 사이트의 주소를 이용했다.

- (IBAction)sendDataUsingGet:(id)sender {
    
    //GET 방식 URL 설정
    //NSString *getURL = [NSString stringWithFormat:@"%@?username=%@&password=%@",GET_URL,usrname,pass];
    
    NSString *getURL = [NSString stringWithFormat:@"%@",GET_URL];
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:getURL]];
    [request setHTTPMethod:@"GET"];
    
    //SESSION 설정
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        if (data!=nil){
            
            //NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
            //NSLog(@"Request reply: %@", requestReply);
            
            NSDictionary* json = [NSJSONSerialization
                                  JSONObjectWithData:data
                                  options:kNilOptions
                                  error:&error];
            NSString *tmp = [NSString stringWithFormat:@"%@", json];
            
            NSLog(@"tmp %@", tmp);
            
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.textArea setText:tmp];
            });
            
            
        }else{
            NSLog(@"error");
        }

    }] resume];
}

 

🔅Post방식으로 호출

Post 방식도 Get방식과 비슷하다. 단지 요청 메소드가 Post로 변경되었다. 그리고 주소는 위와 마찬가지로 

 https://reqres.in/api/users/create의 주소를 사용했다.

//post 방식
- (IBAction)sendDataUsingPost:(id)sender {
    //전송방식이 post일때
    //기본 구성에 URLSession 생성
    NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration];

    // request URL 설정
    NSURL *url = url = [NSURL URLWithString: POST_URL];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    
    
    // UTF8 인코딩을 사용하여 POST 문자열 매개 변수를 데이터로 변환
    NSString *postParams = [NSString stringWithFormat:@"name=%@&job=%@",@"kkang",@"developer"];
    NSData *postData = [postParams dataUsingEncoding:NSUTF8StringEncoding];
    
    // 셋팅
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:postData];
    
    // dataTask 생성
    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    
        if (data!=nil)
        {
            NSDictionary* json = [NSJSONSerialization
                                  JSONObjectWithData:data
                                  options:kNilOptions
                                  error:&error];
            
            NSString *userId = [json objectForKey:@"id"];
            NSString *userName = [json objectForKey:@"name"];
            NSString *userJob = [json objectForKey:@"job"];
            
            NSLog(@"id %@",  userId);
            NSLog(@"name %@",  userName);
            NSLog(@"job %@", userJob);
            
            NSString *tmp = [NSString stringWithFormat:@"%@", json];

            dispatch_async(dispatch_get_main_queue(), ^{
                [self.textArea setText:tmp];
            });
            
           
            
        }else{
            NSLog(@"error");
        }
    }];

    // task 시작
    [dataTask resume];
}

 

🔅화면이 로드될때 Post 요청

아래 소스는 새창열기 버튼을 눌렀을 때 새창의 viewDidload에서 Post 방식으로 요청하는 소스이다. 위에서는 요청이 성공하면 completeHandler를 타게되는데 아래 소스는 델리게이트 메소드들이 각각 호출이되면서 응답여부를 확인한다. 사용된 URL은 위와 동일한

https://reqres.in/api/users/create이다.

@interface SessionController (){
    //POST 요청 주소
    #define POST_URL @"https://reqres.in/api/users/create"
}
@end

@implementation SessionController

//결과 창 변수
@synthesize textArea;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //표준 설정 구하기
    NSURLSessionConfiguration * defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    //캐싱 비활성화
    //defaultConfig.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    
    //Lte 를 이용한 엑세스 허용
    defaultConfig.allowsCellularAccess = YES;
    
    //로컬의 캐시 데이터를 무시하고, 최신 데이터 받기
    defaultConfig.requestCachePolicy = NSURLRequestReturnCacheDataElseLoad;
    
    
    //세션 설정 객체
    NSURLSession * defaultSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    //호출 URL 설정
    NSString * scriptURL = [NSString stringWithFormat:POST_URL];
    
    //URL 문자열을 NSURLSession에서 사용할 수있는 URL로 변환.
    NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:scriptURL]];
    
    NSString * postDataString = [NSString stringWithFormat:@"name=%@&job=%@", @"hongsoo", @"29"];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[postDataString dataUsingEncoding:NSUTF8StringEncoding]];
    
    //태스크 생성
    NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithRequest:urlRequest];

    //태스크를 시작
    [dataTask resume];
}

/*
    응답 처리 델리게이트 메소드
 */

//응답을 수신했을 떼 호출되는 메소드
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{

    NSLog(@" - 응답 수신 완료 - ");
    
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
    
    NSInteger status = [httpResponse statusCode];
    
    NSLog(@"상태 : %ld" , (long)status);
    
    if(status == 201){
        NSLog(@" status : 200 응답 성공 ");

        //NSURLSessionResponseAllow           //테스크 계속 진행
        //NSURLSessionResponseCancel          //읽기 처리 중단
        //NSURLSessionResponseBecomeDownload  //작업을 다운로드 작업으로 변환
        completionHandler(NSURLSessionResponseAllow);
    
    }else{
        
        NSLog(@" status : 응답 실패 ");
        
        completionHandler(NSURLSessionResponseCancel);
    }
    
}
//데이터가 읽혀질 때마다 호출되며, 데이터를 메모리에 저장하는 처리를 한다.
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{

    NSLog(@" - 데이터 메모리에서 처리 - ");
    
    // NSDictionary에 들어온 JSON을 구문 분석
    NSError * err = nil;
    NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&err];

    // 오류가 발생하지 않으면 정상적으로 객체 배열을 분석
    if (!err){
        
        // 여기에서 JSON 'jsonDict' 분석
        NSString *tmp = [NSString stringWithFormat:@"%@", jsonDict];
        
        [self.textArea setText:tmp];
        
        
    //오류가 발생
    }else{
        
            //오류 처리
    }
}


// 처리가 완료 또는 취소된 경우 호출되는 메소드. 에러 발생여부는 error의 내용으로 판단 가능하다.
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    
    NSLog(@" - 세션 처리 완료 - ");
    
    if(error == nil){
        // API에서 성공적으로 다운로드했습니다.
        NSLog(@"Data Network Request Did Complete Successfully.");
    }else{
        // 응답을받지 못하게하는 오류를 설명하고 기록합니다.
        NSLog(@"Error: %@", [error userInfo]);

        //네트워크 오류를 처리하여 사용자에게 발생한 상황을 알립니다.
    }
}

//세션이 챌린지를 받으면 (iOS 9 App Transport Security가 유효하지 않은 SSL 인증서를 차단하기 때문에) 다음 방법을 사용하여 NSURLSession에 "Chill out, I can trust me"를 알립니다.
// 서버가 HTTPS가 아닌 HTTP를 사용하지 않는 한 다음은 필요하지 않다.

/*
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler{
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        if([challenge.protectionSpace.host isEqualToString:@"DomainNameOfServer.io"]){
            NSURLCredential * credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        }
    }
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        if([challenge.protectionSpace.host isEqualToString:@"DomainNameOfServer.io"]){
            NSURLCredential * credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        }
    }
}
 
*/

@end

 

🔅예제파일

Session.zip
0.07MB

 

 

구현은 했지만 개념이 아직잘 안 온다면 이전 포스팅 내용을 잠깐 참고하면 도움이 될것이다.