IOS: как выполнить HTTP-запрос POST?
Я подхожу к разработке iOS, и я хотел бы, чтобы одно из моих первых приложений выполняло HTTP-запрос POST.
Насколько я понимаю, я должен управлять соединением, которое обрабатывает запрос через объект NSURLConnection
, что заставляет меня иметь объект-делегат, который, в свою очередь, будет обрабатывать события данных.
Может ли кто-нибудь прояснить задачу на практическом примере?
Мне нужно связаться с конечной точкой https, отправляющей данные аутентификации (имя пользователя и пароль) и возвращая обычный текстовый ответ.
Ответы
Ответ 1
Вы можете использовать NSURLConnection следующим образом:
-
Установите 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
, которую вы можете обработать.
ВАЖНО: не забудьте запустить синхронный запрос в отдельном потоке, чтобы избежать блокировки пользовательского интерфейса.
-
Асинхронно: (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];
}
Ответ 2
EDIT: ASIHTTPRequest был оставлен разработчиком. Это по-прежнему очень хорошая ИМО, но теперь вы, вероятно, должны искать в другом месте.
Я бы рекомендовал использовать библиотеку ASIHTTPRequest, если вы работаете с HTTPS. Даже без https он обеспечивает действительно приятную оболочку для таких вещей, и, хотя это не сложно сделать самому по простому http, я просто думаю, что библиотека хорошая и отличный способ начать работу.
Утечки HTTPS далеки от тривиальных в различных сценариях, и если вы хотите быть уверенными в обработке всех вариантов, вы найдете настоящую помощь в библиотеке ASI.
Ответ 3
Мне показалось, что я немного обновил этот пост и скажу, что многие из iOS-сообщества перешли на AFNetworking после ASIHTTPRequest
был оставлен. Я очень рекомендую. Это отличная оболочка вокруг NSURLConnection
и позволяет асинхронные вызовы и в основном все, что вам может понадобиться.
Ответ 4
Вот обновленный ответ для 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).
Ответ 5
ПРИМЕЧАНИЕ: пример 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()
}
Ответ 6
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()
URL-адрес: вызов делегата:
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% гарантию результата
Ответ 7
Вот как работает запрос POST HTTP для iOS 8+ с использованием 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];
}
Надеемся, что это удовлетворит ваше следующее требование.