iOS : HTTP POST 요청을 수행하는 방법?


128

iOS 개발에 접근하고 있으며 HTTP POST 요청을 수행하는 첫 번째 응용 프로그램 중 하나를 갖고 싶습니다.

내가 이해할 수있는 한 NSURLConnection객체 를 통해 요청을 처리하는 연결을 관리해야하며 , 이로 인해 위임 객체가 있어야 데이터 이벤트를 처리 할 수 ​​있습니다.

실제 사례를 통해 누군가가 과제를 분명히 설명해 주시겠습니까?

인증 데이터 (사용자 이름 및 비밀번호)를 보내고 일반 텍스트 응답을받는 https 엔드 포인트에 연락해야합니다.

답변:


167

NSURLConnection을 다음과 같이 사용할 수 있습니다.

  1. 설정 NSURLRequest: requestWithURL:(NSURL *)theURL요청을 초기화하는 데 사용 합니다.

    당신은 POST 요청 및 / 또는 HTTP 헤더 사용을 지정해야하는 경우 NSMutableURLRequest

    • (void)setHTTPMethod:(NSString *)method
    • (void)setHTTPBody:(NSData *)data
    • (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
  2. 다음을 사용하여 두 가지 방법으로 요청을 보내십시오 NSURLConnection.

    • 동 기적으로 : (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

      NSData처리 할 수 있는 변수를 반환합니다 .

      중요 : UI를 차단하지 않으려면 별도의 스레드에서 동기 요청을 시작하십시오.

    • 비동기 적으로 : (void)start

NSURLConnection의 델리게이트가 다음과 같이 연결을 처리하도록 설정하는 것을 잊지 마십시오.

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.data setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
    [self.data appendData:d];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"")
                                 message:[error localizedDescription]
                                delegate:nil
                       cancelButtonTitle:NSLocalizedString(@"OK", @"") 
                       otherButtonTitles:nil] autorelease] show];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *responseText = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding];

    // Do anything you want with it 

    [responseText release];
}

// Handle basic authentication challenge if needed
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    NSString *username = @"username";
    NSString *password = @"password";

    NSURLCredential *credential = [NSURLCredential credentialWithUser:username
                                                             password:password
                                                          persistence:NSURLCredentialPersistenceForSession];
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}

4
애플은 동기 요청을 사용하는 것은 "권장하지 않는다"라고 developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… 이라고 말하고있다. 비록 다른 스레드로 혼란 스러울 정도로 충분히 알고 있다면 아마 괜찮을 것이다.
Aaron Brown

@Anh Nice Answer, 그러나 나는 마지막 방법에 약간 회의적이었습니다 didReceiveAuthenticationChallenge. 하드 코딩 암호 / 사용자 이름에 보안 문제가 있습니까? 이 주위에 어떤 방법이 있습니까?
Sam Spencer

2
일반적으로 자격 증명을 키 체인에 저장하고 기본 인증을 처리하기 위해 자격 증명을 검색합니다.
Anh Do

2
iOS 5부터는 + (void) sendAsynchronousRequest : (NSURLRequest ) 요청 대기열 : (NSOperationQueue *) queue completionHandler : (void (^) (NSURLResponse , NSData *, NSError *)) handler
chunkyguy

13

편집 : ASIHTTPRequest가 개발자에 의해 포기되었습니다. 여전히 좋은 IMO이지만 지금은 다른 곳을 봐야합니다.

HTTPS를 처리하는 경우 ASIHTTPRequest 라이브러리를 사용하는 것이 좋습니다 . https가 없어도 이와 같은 것들을위한 정말 좋은 래퍼를 제공하며 일반 http를 통해 자신을하기가 어렵지 않지만 라이브러리는 훌륭하고 시작하는 좋은 방법이라고 생각합니다.

HTTPS 복잡한 문제는 다양한 시나리오에서 사소한 문제가 아니며 모든 변형을 강력하게 처리하려면 ASI 라이브러리가 도움이 될 것입니다.


13
ASIHTTPRequest 라이브러리는 개발자가이 게시물을 다음과 같이 공식적으로 폐기했습니다. allseeing-i.com/[request_release] ; 개발자가 제안한대로 다른 라이브러리를 사용하거나 NSURLRequest를 배우려고 시도하는 것이 좋습니다. :) 건배.
Goles

@ Mr.Gando-링크가 작동하지 않는 것 같습니다. 세미콜론은 중요합니다. 그것은, 그것이 버려진 것을보고 매우 슬 said습니다. 그것은 정말 많은 인증 작업을 훌륭하게 수행하고 그것을 모두 복제하는 많은 일입니다 ... 부끄러운 ...
Roger

그리고 그 링크도 작동하지 않습니다. 그것을 찾으려고하는 사람은 올바른 URL 끝에 세미콜론이 필요합니다. 사람들이 게시하는 링크에서 제외됩니다.
Roger

3
AFNetworking 은 현재 대부분의 사람들이 사용하고있는 것입니다.
Vadoff

7

나는이 글을 조금 업데이트하고 아이폰 OS 커뮤니티의 많이가까지 이동 한 말을 생각 AFNetworkingASIHTTPRequest포기했다. 나는 그것을 강력히 추천합니다. 그것은 훌륭한 래퍼 NSURLConnection이며 비동기식 호출과 기본적으로 필요한 모든 것을 허용합니다.


2
나는 받아 들인 대답이 좋다는 것을 알고, 행동이나 다른 것을 의미하지는 않지만, 분명히 더 많은 공의가 있어야합니다. 아마도 질문과 같이 예제와 일부 코드 조각이 추가된다면?
acrespo

6

다음은 iOS7 +에 대한 업데이트 된 답변입니다. 새로운 핫 니스 인 NSURLSession을 사용합니다. 면책 조항, 이것은 테스트되지 않았으며 텍스트 필드에 작성되었습니다.

- (void)post {
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/dontposthere"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    // Uncomment the following two lines if you're using JSON like I imagine many people are (the person who is asking specified plain text)
    // [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    // [request addValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
    [request setHTTPMethod:@"POST"];
    NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }];
    [postDataTask resume];
}

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(    NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}

또는 AFNetworking 2.0 이상을 사용하십시오. 일반적으로 AFHTTPSessionManager를 서브 클래스로 만들지 만 간결한 예제를 얻기 위해이 모든 것을 하나의 방법으로 넣습니다.

- (void)post {
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"https://example.com"]];
    // Many people will probably want [AFJSONRequestSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    // Many people will probably want [AFJSONResponseSerializer serializer];
    manager.responseSerializer = [AFHTTPRequestSerializer serializer];
    manager.securityPolicy.allowInvalidCertificates = NO; // Some servers require this to be YES, but default is NO.
    [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"username" password:@"password"];
    [[manager POST:@"dontposthere" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
        NSString *responseString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"darn it");
    }] resume];
}

JSON 응답 시리얼 라이저를 사용하는 경우 responseObject는 JSON 응답의 객체 (종종 NSDictionary 또는 NSArray)입니다.


1

참고 : Pure Swift 3 (Xcode 8) 예 : 다음 샘플 코드를 사용해보십시오. 의 간단한 dataTask기능 예 입니다 URLSession.

func simpleDataRequest() {

        //Get the url from url string
        let url:URL = URL(string: "YOUR URL STRING")!

        //Get the session instance
        let session = URLSession.shared

        //Create Mutable url request
        var request = URLRequest(url: url as URL)

        //Set the http method type
        request.httpMethod = "POST"

        //Set the cache policy
        request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData

        //Post parameter
        let paramString = "key=value"

        //Set the post param as the request body
        request.httpBody = paramString.data(using: String.Encoding.utf8)

        let task = session.dataTask(with: request as URLRequest) {
            (data, response, error) in

            guard let _:Data = data as Data?, let _:URLResponse = response  , error == nil else {

                //Oops! Error occured.
                print("error")
                return
            }

            //Get the raw response string
            let dataString = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))

            //Print the response
            print(dataString!)

        }

        //resume the task
        task.resume()

    }

0

Xcode 8 및 Swift 3.0

URLSession 사용 :

 let url = URL(string:"Download URL")!
 let req = NSMutableURLRequest(url:url)
 let config = URLSessionConfiguration.default
 let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)

 let task : URLSessionDownloadTask = session.downloadTask(with: req as URLRequest)
task.resume()

URLSession 대리인 전화 :

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {

}


func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, 
didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
                   print("downloaded \(100*writ/exp)" as AnyObject)

}

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL){

}

GET / POST / PUT / DELETE 차단 사용 :

 let request = NSMutableURLRequest(url: URL(string: "Your API URL here" ,param: param))!,
        cachePolicy: .useProtocolCachePolicy,
        timeoutInterval:"Your request timeout time in Seconds")
    request.httpMethod = "GET"
    request.allHTTPHeaderFields = headers as? [String : String] 

    let session = URLSession.shared

    let dataTask = session.dataTask(with: request as URLRequest) {data,response,error in
        let httpResponse = response as? HTTPURLResponse

        if (error != nil) {
         print(error)
         } else {
         print(httpResponse)
         }

        DispatchQueue.main.async {
           //Update your UI here
        }

    }
    dataTask.resume()

나를 위해 잘 작동합니다. 100 % 결과 보장


0

NSURLSession을 사용하여 iOS 8 이상에서 POST HTTP 요청이 작동하는 방법은 다음과 같습니다.

- (void)call_PostNetworkingAPI:(NSURL *)url withCompletionBlock:(void(^)(id object,NSError *error,NSURLResponse *response))completion
{
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    config.URLCache = nil;
    config.timeoutIntervalForRequest = 5.0f;
    config.timeoutIntervalForResource =10.0f;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
    NSMutableURLRequest *Req=[NSMutableURLRequest requestWithURL:url];
    [Req setHTTPMethod:@"POST"];

    NSURLSessionDataTask *task = [session dataTaskWithRequest:Req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {

            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
            if (dict != nil) {
                completion(dict,error,response);
            }
        }else
        {
            completion(nil,error,response);
        }
    }];
    [task resume];

}

이것이 다음 요구 사항을 충족시키기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.