iOS: comment effectuer une requête HTTP POST?
J'approche du développement iOS et j'aimerais avoir une de mes premières applications pour effectuer une requête HTTP POST.
Pour autant que je puisse comprendre, je devrais gérer la connexion qui gère la requête via un objet NSURLConnection
, ce qui me force à avoir un objet délégué, qui à son tour gérera les événements de données.
Quelqu'un pourrait-il clarifier la tâche avec un exemple pratique?
Je devrais contacter un point de terminaison https envoyant des données d'authentification (nom d'utilisateur et mot de passe) et récupérer une réponse en texte brut.
7 réponses
Vous pouvez utiliser NSURLConnection comme suit:
-
Définissez votre
NSURLRequest
: Utilisation derequestWithURL:(NSURL *)theURL
initialiser la demande.Si vous devez spécifier une requête POST et / ou des en-têtes HTTP, Utilisez
NSMutableURLRequest
avec(void)setHTTPMethod:(NSString *)method
(void)setHTTPBody:(NSData *)data
(void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
-
Envoyez votre demande de 2 façons en utilisant
NSURLConnection
:-
Synchrone:
(NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
Cela renvoie une variable
NSData
que vous pouvez processus.IMPORTANT: N'oubliez pas de lancer la requête synchrone dans un thread séparé pour éviter de bloquer l'interface utilisateur.
De façon Asynchrone:
(void)start
-
N'oubliez pas de définir le délégué de votre NSURLConnection pour gérer la connexion comme suit:
- (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];
}
EDIT: ASIHTTPRequest a été abandonné par le développeur. C'est toujours très bon IMO, mais vous devriez probablement regarder ailleurs maintenant.
Je recommande fortement d'utiliser la bibliothèque ASIHTTPRequest Si vous gérez HTTPS. Même sans https, il fournit un wrapper vraiment sympa pour des choses comme ça et bien qu'il ne soit pas difficile de faire vous-même sur HTTP simple, je pense juste que la Bibliothèque est agréable et un excellent moyen de commencer.
Les complications HTTPS sont loin d'être trivial dans divers scénarios, et si vous voulez être robuste dans la gestion de toutes les variations, vous trouverez la bibliothèque ASI une aide réelle.
Je pensais mettre à jour un peu ce post et dire que beaucoup de la communauté iOS a déménagé à AFNetworking après ASIHTTPRequest
a été abandonné. Je le recommande fortement. C'est un excellent wrapper autour de NSURLConnection
et permet des appels asynchrones, et fondamentalement tout ce dont vous pourriez avoir besoin.
Voici une réponse mise à jour pour iOS7+. Il utilise NSURLSession, le nouveau hotness. Avertissement, ceci n'est pas testé et a été écrit dans un champ de texte:
- (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]);
}
Ou mieux encore, utilisez AFNetworking 2.0+. Habituellement, je classerais AFHTTPSessionManager, mais je mets tout cela dans une méthode pour avoir un exemple concis.
- (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];
}
Si vous utilisez le sérialiseur de réponse JSON, le responseObject sera objet de la réponse JSON (souvent NSDictionary ou NSArray).
Remarque: Pure Swift 3 (Xcode 8) Exemple:
Veuillez essayer l'exemple de code suivant. C'est l'exemple simple de la fonction dataTask
de 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()
}
Xcode 8 et rapide 3.0
Utiliser 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()
Appel du délégué 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){
}
Utilisation du bloc 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()
Ça marche bien pour moi.. essayez-le 100% garantie de résultat
Voici comment fonctionne la requête POST HTTP pour iOS 8 + en utilisant 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];
}
Espérons que cela satisfera votre exigence suivante.