iOS:如何执行 HTTP POST 请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5537297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:26:53  来源:igfitidea点击:

iOS: how to perform a HTTP POST request?

iphoneobjective-cios

提问by Federico Zancan

I'm approaching iOS development and I'd like to have one of my first applications to perform a HTTP POST request.

我正在接近 iOS 开发,我想要我的第一个应用程序来执行 HTTP POST 请求。

As far as I can understand, I should manage the connection which handles the request via a NSURLConnectionobject, which forces me to have a delegate object, which in turn will handle data events.

据我所知,我应该管理通过NSURLConnection对象处理请求的连接,这迫使我拥有一个委托对象,该对象又将处理数据事件。

Could someone please clarify the task with a practical example?

有人可以用一个实际的例子来澄清这个任务吗?

I should contact an https endpoint sending authentication data (username and password) and getting back a plain text response.

我应该联系发送身份验证数据(用户名和密码)并返回纯文本响应的 https 端点。

回答by Anh Do

You can use NSURLConnection as follows:

您可以使用 NSURLConnection 如下:

  1. Set your NSURLRequest: Use requestWithURL:(NSURL *)theURLto initialise the request.

    If you need to specify a POST request and/or HTTP headers, use NSMutableURLRequestwith

    • (void)setHTTPMethod:(NSString *)method
    • (void)setHTTPBody:(NSData *)data
    • (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
  2. Send your request in 2 ways using NSURLConnection:

    • Synchronously: (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

      This returns a NSDatavariable that you can process.

      IMPORTANT: Remember to kick off the synchronous request in a separate thread to avoid blocking the UI.

    • Asynchronously: (void)start

  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

Don't forget to set your NSURLConnection's delegate to handle the connection as follows:

不要忘记设置您的 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];
}

回答by Roger

EDIT: ASIHTTPRequest has been abandoned by the developer. It's still really good IMO, but you should probably look elsewhere now.

编辑: ASIHTTPRequest 已被开发人员放弃。它仍然是非常好的 IMO,但你现在应该看看其他地方。

I'd highly recommend using the ASIHTTPRequest libraryif you are handling HTTPS. Even without https it provides a really nice wrapper for stuff like this and whilst it's not hard to do yourself over plain http, I just think the library is nice and a great way to get started.

如果您正在处理 HTTPS,我强烈建议您使用ASIHTTPRequest 库。即使没有 https,它也为这样的东西提供了一个非常好的包装器,虽然通过普通的 http 做自己并不难,但我只是认为这个库很好,是一个很好的入门方式。

The HTTPS complications are far from trivial in various scenarios, and if you want to be robust in handling all the variations, you'll find the ASI library a real help.

HTTPS 的复杂性在各种情况下都不是微不足道的,如果您想在处理所有变体时保持稳健,您会发现 ASI 库是一个真正的帮助。

回答by Jesse Naugher

I thought I would update this post a bit and say that alot of the iOS community has moved over to AFNetworkingafter ASIHTTPRequestwas abandoned. I highly recommend it. It's a great wrapper around NSURLConnectionand allows for asynchronous calls, and basically anything you might need.

我想我会稍微更新一下这篇文章,并说很多 iOS 社区在被放弃后已经转移到AFNetworkingASIHTTPRequest。我强烈推荐它。它是一个很好的包装器NSURLConnection,允许异步调用,以及您可能需要的任何东西。

回答by Kyle Robson

Here is an updated answer for iOS7+. It uses NSURLSession, the new hotness. Disclaimer, this is untested and was written in a text field:

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

Or better yet, use AFNetworking 2.0+. Usually I would subclass AFHTTPSessionManager, but I'm putting this all in one method to have a concise example.

或者更好的是,使用 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];
}

If you are using the JSON response serializer, the responseObject will be object from the JSON response (often NSDictionary or NSArray).

如果您使用 JSON 响应序列化程序,则 responseObject 将是来自 JSON 响应的对象(通常是 NSDictionary 或 NSArray)。

回答by Dinesh

NOTE: Pure Swift 3 (Xcode 8) example:Please try out the following sample code. It is the simple example of dataTaskfunction of URLSession.

注意: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()

    }

回答by Saumil Shah

Xcode 8 and Swift 3.0

Xcode 8 和 Swift 3.0

Using URLSession:

使用 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 Delegate call:

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){

}

Using Block GET/POST/PUT/DELETE:

使用块 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()

Working fine for me.. try it 100% result guarantee

对我来说工作正常.. 尝试 100% 结果保证

回答by Abilash Balasubramanian

Here is how POST HTTP request works for iOS 8+ using NSURLSession:

以下是使用 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];

}

Hope this will satisfy your following requirement.

希望这将满足您的以下要求。