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
iOS: how to perform a HTTP POST request?
提问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 NSURLConnection
object, 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 如下:
Set your
NSURLRequest
: UserequestWithURL:(NSURL *)theURL
to initialise the request.If you need to specify a POST request and/or HTTP headers, use
NSMutableURLRequest
with(void)setHTTPMethod:(NSString *)method
(void)setHTTPBody:(NSData *)data
(void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
Send your request in 2 ways using
NSURLConnection
:Synchronously:
(NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
This returns a
NSData
variable that you can process.IMPORTANT: Remember to kick off the synchronous request in a separate thread to avoid blocking the UI.
Asynchronously:
(void)start
设置您的
NSURLRequest
:requestWithURL:(NSURL *)theURL
用于初始化请求。如果你需要指定一个POST请求和/或HTTP头,使用
NSMutableURLRequest
与(void)setHTTPMethod:(NSString *)method
(void)setHTTPBody:(NSData *)data
(void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
使用
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 ASIHTTPRequest
was abandoned. I highly recommend it. It's a great wrapper around NSURLConnection
and 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 dataTask
function 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.
希望这将满足您的以下要求。