iOS: làm thế nào để thực hiện yêu cầu POST HTTP?


128

Tôi đang tiếp cận phát triển iOS và tôi muốn có một trong những ứng dụng đầu tiên của mình thực hiện yêu cầu HTTP POST.

Theo như tôi có thể hiểu, tôi nên quản lý kết nối xử lý yêu cầu thông qua một NSURLConnectionđối tượng, điều này buộc tôi phải có một đối tượng ủy nhiệm, từ đó sẽ xử lý các sự kiện dữ liệu.

Ai đó có thể xin vui lòng làm rõ nhiệm vụ với một ví dụ thực tế?

Tôi nên liên hệ với điểm cuối gửi dữ liệu xác thực https (tên người dùng và mật khẩu) và nhận lại phản hồi bằng văn bản.

Câu trả lời:


167

Bạn có thể sử dụng NSURLConnection như sau:

  1. Đặt của bạn NSURLRequest: Sử dụng requestWithURL:(NSURL *)theURLđể khởi tạo yêu cầu.

    Nếu bạn cần chỉ định một yêu cầu POST và / hoặc tiêu đề HTTP, hãy sử dụng NSMutableURLRequestvới

    • (void)setHTTPMethod:(NSString *)method
    • (void)setHTTPBody:(NSData *)data
    • (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
  2. Gửi yêu cầu của bạn theo 2 cách sử dụng NSURLConnection:

    • Đồng bộ: (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

      Điều này trả về một NSDatabiến mà bạn có thể xử lý.

      QUAN TRỌNG: Hãy nhớ khởi động yêu cầu đồng bộ trong một luồng riêng biệt để tránh chặn UI.

    • Không đồng bộ: (void)start

Đừng quên đặt đại biểu NSURLConnection của bạn để xử lý kết nối như sau:

- (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
Apple nói rằng việc sử dụng các yêu cầu đồng bộ là "không được khuyến nghị" developer.apple.com/l Library / mac / # document / Cocoa / Conceptionual / Mặc dù nếu bạn biết đủ để làm phiền với các luồng khác nhau, có lẽ bạn sẽ ổn.
Aaron Brown

@Anh Nice Trả lời, nhưng tôi hơi nghi ngờ với phương pháp cuối cùng didReceiveAuthenticationChallenge. Có bất kỳ vấn đề bảo mật với mật khẩu / tên người dùng mã hóa cứng? Có cách nào để khắc phục điều này?
Sam Spencer

2
Nói chung, bạn sẽ lưu trữ thông tin đăng nhập trong móc khóa và truy xuất chúng ở đó để xử lý Basic-Auth.
Anh Đỗ

2
iOS 5 trở đi cũng có thể sử dụng + (void) sendAsynchronousRequest: (NSURLRequest ) yêu cầu đợi: (NSOperationQueue *) đợi completionHandler: (void (^) (NSURLResponse , NSData *, NSError *)) handler
chunkyguy

13

EDIT: ASIHTTPRequest đã bị nhà phát triển bỏ rơi. IMO vẫn thực sự tốt, nhưng có lẽ bạn nên tìm nơi khác ngay bây giờ.

Tôi thực sự khuyên bạn nên sử dụng thư viện ASIHTTPRequest nếu bạn đang xử lý HTTPS. Ngay cả khi không có https, nó vẫn cung cấp một trình bao bọc thực sự tốt cho những thứ như thế này và trong khi bạn không khó để tự mình vượt qua http đơn giản, tôi chỉ nghĩ rằng thư viện rất hay và là một cách tuyệt vời để bắt đầu.

Các biến chứng HTTPS khác xa với các tình huống khác nhau và nếu bạn muốn mạnh mẽ trong việc xử lý tất cả các biến thể, bạn sẽ thấy thư viện ASI là một trợ giúp thực sự.


13
Thư viện ASIHTTPRequest đã bị nhà phát triển của nó chính thức bỏ rơi vì bài đăng này nêu rõ: allecting-i.com/[request_release] ; , Tôi sẽ khuyên bạn nên sử dụng các thư viện khác như nhà phát triển gợi ý, hoặc thậm chí tốt hơn, hãy thử tìm hiểu NSURLRequest :) Chúc mừng.
Goles

@ Mr.Gando - liên kết của bạn dường như không hoạt động - lưu ý rằng dấu chấm phẩy rất quan trọng. Điều đó nói rằng, RẤT buồn khi thấy nó bị bỏ rơi. Nó thực hiện rất nhiều công cụ xác thực thực sự độc đáo và rất nhiều công việc để sao chép tất cả ... xấu hổ ...
Roger

Và liên kết đó cũng không hoạt động. Đối với bất kỳ ai đang cố gắng tìm nó, xin lưu ý url chính xác yêu cầu một dấu chấm phẩy ở cuối của nó - SO đang gây ra; để được loại trừ khỏi các liên kết mọi người đang đăng.
Roger

3
AFNetworking là những gì hầu hết mọi người dường như đang sử dụng bây giờ.
Vadoff

7

Tôi nghĩ rằng tôi sẽ cập nhật bài đăng này một chút và nói rằng rất nhiều cộng đồng iOS đã chuyển sang AFNetworking sau khi ASIHTTPRequestbị bỏ rơi. Tôi khuyên bạn nên nó. Đó là một trình bao bọc tuyệt vời xung quanh NSURLConnectionvà cho phép các cuộc gọi không đồng bộ, và về cơ bản là bất cứ điều gì bạn có thể cần.


2
Tôi biết câu trả lời được chấp nhận là tốt, không có nghĩa là để hạ thấp hoặc bất cứ điều gì, nhưng điều này chắc chắn sẽ có nhiều sự ủng hộ hơn. Có lẽ nếu một ví dụ và một số đoạn mã được thêm vào, như câu hỏi gợi ý?
acrespo

6

Dưới đây là câu trả lời cập nhật cho iOS7 +. Nó sử dụng NSURLSession, độ nóng mới. Từ chối trách nhiệm, điều này chưa được kiểm tra và được viết trong một trường văn bản:

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

Hoặc tốt hơn nữa, sử dụng AFNetworking 2.0+. Thông thường tôi sẽ phân lớp AFHTTPSessionManager, nhưng tôi sẽ đặt tất cả trong một phương thức này để có một ví dụ ngắn gọn.

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

Nếu bạn đang sử dụng trình tuần tự hóa phản hồi JSON, answerObject sẽ là đối tượng từ phản hồi JSON (thường là NSDipedia hoặc NSArray).


1

LƯU Ý: Ví dụ Pure Swift 3 (Xcode 8): Vui lòng thử mã mẫu sau. Đây là ví dụ đơn giản về dataTaskchức năng của 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 và Swift 3.0

Sử dụng 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()

Cuộc gọi đại biểu 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){

}

Sử dụng Khối 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()

Làm việc tốt cho tôi .. hãy thử đảm bảo 100% kết quả


0

Dưới đây là cách yêu cầu POST HTTP hoạt động cho iOS 8+ bằng NSURLSession:

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

}

Hy vọng điều này sẽ đáp ứng yêu cầu sau đây của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.