iOS:如何执行HTTP POST请求?


128

我正在进行iOS开发,我想拥有第一个执行HTTP POST请求的应用程序之一。

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

有人可以用一个实际的例子来阐明任务吗?

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

Answers:


167

您可以按如下方式使用NSURLConnection:

  1. 设置您的NSURLRequestrequestWithURL:(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/... 但如果你足够了解周围的混乱与不同的线程,你可能会被罚款。
亚伦·布朗

@Anh Nice Answer,但是我对最后一种方法有些怀疑didReceiveAuthenticationChallenge。硬编码的密码/用户名是否存在任何安全问题?有没有办法解决?
Sam Spencer

2
通常,您会将凭据存储在钥匙串中,然后在其中检索它们以处理Basic-Auth。
Anh Do

2
iOS 5及更高版本还可以使用+(void)sendAsynchronousRequest:(NSURLRequest )请求队列:(NSOperationQueue *)队列完成处理程序:(void(^)(NSURLResponse,NSData *,NSError *))处理程序
chunkyguy 2013年

13

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

如果您要处理HTTPS,我强烈建议使用ASIHTTPRequest库。即使没有https,它也为此类内容提供了一个非常不错的包装器,尽管通过纯HTTP进行操作并不困难,但我只是认为该库是不错的,而且是入门的好方法。

在各种情况下,HTTPS的复杂性都不是小事,如果您想稳健地处理所有变体,您会发现ASI库是真正的帮助。


13
ASIHTTPRequest库已被其开发人员正式放弃,其内容如下:allseeing-i.com/[request_release] ; ,我建议您按照开发人员的建议使用其他库,或者甚至更好地尝试学习NSURLRequest :)干杯。
Goles 2011年

@ Mr.Gando-您的链接似乎无效-请注意,分号很重要。这就是说,很伤心看到它抛弃了。它确实很好地完成了很多身份验证工作,要复制所有内容,还要做很多工作……可耻...
罗杰(Roger)

而且该链接也不起作用。对于任何尝试查找它的人,请注意正确的URL要求在其末尾使用分号-这样会导致; 从人们发布的链接中排除。
罗杰

3
大多数人似乎现在正在使用AFNetworking
Vadoff

7

我以为我会对此文章进行一些更新,并说很多iOS社区在被抛弃后已转移到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的POST HTTP请求在iOS 8+上的工作方式:

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

}

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.