iOS: HTTP POST isteği nasıl gerçekleştirilir?


127

İOS geliştirmeye yaklaşıyorum ve ilk uygulamalarımdan birinin bir HTTP POST isteği gerçekleştirmesini istiyorum.

Anladığım kadarıyla, isteği bir NSURLConnectionnesne aracılığıyla işleyen bağlantıyı yönetmeliyim , bu da beni bir temsilci nesnesine sahip olmaya zorluyor ve bu da veri olaylarını işleyecek.

Biri lütfen pratik bir örnekle görevi netleştirebilir mi?

Kimlik doğrulama verilerini (kullanıcı adı ve şifre) gönderen ve düz metin yanıtını geri alan bir https uç noktasıyla iletişime geçmeliyim.

Yanıtlar:


166

NSURLConnection'ı aşağıdaki şekilde kullanabilirsiniz:

  1. Ayarlayın NSURLRequest: requestWithURL:(NSURL *)theURLTalebi başlatmak için kullanın .

    Eğer bir POST isteği ve / veya HTTP başlıkları kullanın belirtmek gerekirse NSMutableURLRequestile

    • (void)setHTTPMethod:(NSString *)method
    • (void)setHTTPBody:(NSData *)data
    • (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
  2. İsteğinizi kullanarak 2 şekilde gönderin NSURLConnection:

    • Eş zamanlı: (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

      Bu NSData, işleyebileceğiniz bir değişken döndürür .

      ÖNEMLİ: Kullanıcı arayüzünü engellemekten kaçınmak için eşzamanlı isteği ayrı bir iş parçacığında başlatmayı unutmayın.

    • uyumsuz: (void)start

NSURLConnection'ınızın temsilcisini aşağıdaki gibi bağlantıyı yönetecek şekilde ayarlamayı unutmayın:

- (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
Apple, eşzamanlı istekleri kullanmanın "tavsiye edilmediğini" söylüyor developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…, ancak farklı iş parçacıklarıyla uğraşmak için yeterince bilginiz varsa, muhtemelen iyi olacaksınız.
Aaron Brown

@Anh Güzel Cevap, ama son yöntem konusunda biraz şüpheliydim didReceiveAuthenticationChallenge. Sabit kodlama parolaları / kullanıcı adlarıyla ilgili herhangi bir güvenlik sorunu var mı? Bunun etrafında herhangi bir yol var mı?
Sam Spencer

2
Genellikle kimlik bilgilerini anahtar zincirinde saklarsınız ve Temel Kimlik Doğrulamasını işlemek için onları orada alırsınız.
Anh Do

2
iOS 5 sonrası + (void) sendAsynchronousRequest: (NSURLRequest ) istek kuyruğu: (NSOperationQueue *) kuyruk tamamlamaHandler: (void (^) (NSURLResponse , NSData *, NSError *)) işleyici
chunkyguy

13

DÜZENLE: ASIHTTPRequest geliştirici tarafından terk edildi. Hala gerçekten iyi bir IMO, ancak muhtemelen şimdi başka bir yere bakmalısınız.

HTTPS ile uğraşıyorsanız ASIHTTPRequest kitaplığını kullanmanızı şiddetle tavsiye ederim . Https olmadan bile, bunun gibi şeyler için gerçekten güzel bir sarmalayıcı sağlar ve kendinizi düz http üzerinden yapmak zor olmasa da, kütüphanenin güzel ve başlamak için harika bir yol olduğunu düşünüyorum.

HTTPS komplikasyonları, çeşitli senaryolarda önemsiz olmaktan çok uzaktır ve tüm varyasyonları işlemede güçlü olmak istiyorsanız, ASI kitaplığının gerçek bir yardım olduğunu göreceksiniz.


13
ASIHTTPRequest kitaplığı, şu yayında belirtildiği gibi geliştiricisi tarafından resmi olarak terk edilmiştir: allseeing-i.com/[request_release] ; , Geliştiricinin önerdiği gibi diğer kitaplıkları kullanmanızı veya daha iyisi NSURLRequest'i öğrenmeye çalışmanızı tavsiye ederim :) Şerefe.
Goles

@ Bay Gando - bağlantınız çalışmıyor - noktalı virgülün önemli olduğunu unutmayın. Bununla birlikte, terk edildiğini görmek ÇOK üzücü. Kimlik doğrulama işlerinin çoğunu gerçekten güzel bir şekilde yapıyor ve hepsini çoğaltmak çok iş gerektiriyor ... yazık ...
Roger

Ve bu bağlantı da çalışmıyor. Onu bulmaya çalışan herkes için, lütfen doğru url'nin sonunda noktalı virgül gerektirdiğini unutmayın - SO; insanların gönderdiği bağlantılardan dışlanacak.
Roger

3
AFNetworking şu anda çoğu insanın kullandığı şeydir.
Vadoff

7

Bu yazıyı biraz güncelleyeceğimi ve iOS topluluğunun birçoğununASIHTTPRequest terk edildikten sonra AFNetworking'e geçtiğini söyleyeceğimi düşündüm . Şiddetle tavsiye ederim. Etrafında harika bir sarmalayıcıdır NSURLConnectionve eşzamansız çağrılara ve temelde ihtiyacınız olabilecek her şeye izin verir.


2
Kabul edilen cevabın iyi olduğunu biliyorum, alçakgönüllülük falan demek istemiyorum, ama bu kesinlikle daha fazla olumlu oy almalı. Belki de sorudan da anlaşılacağı gibi bir örnek ve bir kod parçası eklenirse?
acrespo

6

İşte iOS7 + için güncellenmiş bir cevap. Yeni güzellik olan NSURLSession'ı kullanır. Sorumluluk reddi beyanı, bu test edilmemiştir ve bir metin alanına yazılmıştır:

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

Ya da daha iyisi, AFNetworking 2.0+ kullanın. Genellikle AFHTTPSessionManager'ın alt sınıfını kullanırdım, ancak kısa bir örnek olması için hepsini tek bir yönteme koyuyorum.

- (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 yanıt serileştiricisini kullanıyorsanız, responseObject JSON yanıtının nesnesi olacaktır (genellikle NSDictionary veya NSArray).


1

NOT: Pure Swift 3 (Xcode 8) örneği: Lütfen aşağıdaki örnek kodu deneyin. dataTaskİşlevinin basit bir örneğidir 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 ve Swift 3.0

URLSession Kullanımı:

 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 Delege çağrısı:

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

}

Blok GET / POST / PUT / DELETE'i kullanma:

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

Benim için iyi çalışıyor .. deneyin% 100 sonuç garantisi


0

NSURLSession kullanılarak iOS 8+ için POST HTTP isteği şu şekilde çalışır:

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

}

Umarım bu, aşağıdaki gereksiniminizi karşılayacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.