Zbliżam się do rozwoju iOS i chciałbym mieć jedną z moich pierwszych aplikacji do wykonywania żądania HTTP POST.
O ile rozumiem, powinienem zarządzać połączeniem, które obsługuje żądanie za pośrednictwem NSURLConnection
obiektu, co zmusza mnie do posiadania obiektu delegata, który z kolei będzie obsługiwał zdarzenia danych.
Czy ktoś mógłby wyjaśnić zadanie na praktycznym przykładzie?
Powinienem skontaktować się z punktem końcowym https wysyłającym dane uwierzytelniające (nazwa użytkownika i hasło) i otrzymującym odpowiedź w postaci zwykłego tekstu.
źródło
didReceiveAuthenticationChallenge
. Czy są jakieś problemy z zabezpieczeniami związane z zakodowanymi na stałe hasłami / nazwami użytkowników? Czy można to obejść?EDYCJA: ASIHTTPRequest został porzucony przez programistę. To wciąż naprawdę dobre IMO, ale prawdopodobnie powinieneś teraz poszukać gdzie indziej.
Gorąco polecam korzystanie z biblioteki ASIHTTPRequest, jeśli obsługujesz HTTPS. Nawet bez https zapewnia naprawdę fajne opakowanie dla takich rzeczy i chociaż nie jest trudno zrobić to samemu za pomocą zwykłego http, po prostu myślę, że biblioteka jest fajna i świetny sposób na rozpoczęcie.
Komplikacje HTTPS nie są trywialne w różnych scenariuszach, a jeśli chcesz być solidny w obsłudze wszystkich odmian, biblioteka ASI będzie naprawdę pomocna.
źródło
Pomyślałem, że zaktualizuję nieco ten post i powiem, że większość społeczności iOS przeniosła się do AFNetworking po tym, jak
ASIHTTPRequest
została porzucona. Gorąco polecam. Jest to świetne opakowanieNSURLConnection
i umożliwia wywołania asynchroniczne i w zasadzie wszystko, czego możesz potrzebować.źródło
Oto zaktualizowana odpowiedź na iOS7 +. Używa NSURLSession, nowej popularności. Zastrzeżenie, to nie zostało przetestowane i zostało napisane w polu tekstowym:
- (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]); }
Lub jeszcze lepiej, użyj AFNetworking 2.0+. Zwykle podklasę tworzyłbym AFHTTPSessionManager, ale umieszczam to wszystko w jednej metodzie, aby uzyskać zwięzły przykład.
- (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]; }
Jeśli używasz serializatora odpowiedzi JSON, responseObject będzie obiektem z odpowiedzi JSON (często NSDictionary lub NSArray).
źródło
UWAGA: Przykład Pure Swift 3 (Xcode 8): Wypróbuj następujący przykładowy kod. To jest prosty przykład
dataTask
funkcjiURLSession
.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() }
źródło
Xcode 8 i Swift 3.0
Korzystanie z sesji URL:
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()
Połączenie delegata 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){ }
Korzystanie z funkcji Block 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()
U mnie działa dobrze… spróbuj 100% gwarancji wyniku
źródło
Oto jak działa żądanie POST HTTP dla iOS 8+ przy użyciu 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]; }
Mam nadzieję, że spełni to następujące wymagania.
źródło