Хобрук: Ваш путь к мастерству в программировании

Как выполнять запросы GET и POST в Swift?

Я адаптировал это из учебника iOS Apprentice Рэя Вендерлиха, часть 4.

Однако этот код работает как запрос GET, отправленный моему Strongloop API с простой моделью базы данных:

  1. Это работает, но я не знаю, почему это работает, так как он не вызывает метод, который я вижу, чтобы фактически отправить запрос.

  2. Я не вижу возможности превратить это в POST-запрос.

Мой вопрос: как выполнить запрос POST? Это делается совсем по-другому?

Дайте мне знать, если вам нужна дополнительная информация.

    class ViewController: UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func getFromDB() {
        let url = urlWithSearchText("")
        println("URL: '\(url)'")
        if let jsonString = performGetRequestWithURL(url) {
            println("Received JSON string '\(jsonString)'")
        }
    }


    func urlWithSearchText(searchText: String) -> NSURL {
        let escapedSearchText = searchText.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
        let urlString = String(format: "http://localhost:3000/api/Tests", escapedSearchText)
        let url = NSURL(string: urlString)
        return url!
    }    

    func performGetRequestWithURL(url: NSURL) -> String? {
        var error: NSError?
        if let resultString = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) {
            return resultString
        } else if let error = error {
            println("Download Error: \(error)")
        } else {
            println("Unknown Download Error")
        }
        return nil
    }

Вот фото этой работы:

https://dl.dropboxusercontent.com/u/14464971/Images/Messages%20Image%281477993527%29.png


Ответы:


1

Ниже приведены два метода POST. В зависимости от того, хотите ли вы, чтобы он был синхронным (все остальное ждет завершения метода post) или асинхронным (метод POST выполняется в фоновом режиме, другие методы выполняются параллельно).

Методы

// POST data to url
func postDataAsynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ()) {
    var URL: NSURL = NSURL(string: url)!
    var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
    request.HTTPMethod = "POST";
    request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){

        response, data, error in

        var output: String!

        if data != nil {
            output = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
        }

        completionHandler(responseString: output, error: error)
    }
}

// Obtain the data
func postDataSynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ())
{
    let URL: NSURL = NSURL(string: url)!
    var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
    request.HTTPMethod = "POST"
    request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

    var response: NSURLResponse?
    var error: NSError?

    // Send data
    let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)

    var output: String! // Default to nil

    if data != nil{
        output =  NSString(data: data!, encoding: NSUTF8StringEncoding) as! String
    }

    completionHandler(responseString: output, error: error)

}

Использование

Затем вы можете вызывать (использовать) их так:

postDataSynchronous(url, bodyData: bodyData) {
    responseString, error in

        if error != nil {
            println("Error during post: \(error)")
            return
        }
        else{
            //Success
            println(responseString)
            userType = responseString // Set usertype based on server response
        }        
    }

SWIFT 2.0

func postData(url: String, params: Dictionary<String, String>, completionHandler: (data: NSData?, response: NSURLResponse?, error: NSError?) -> ()) {

    // Indicate download
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    let url = NSURL(string: url)!
    //        print("URL: \(url)")
    let request = NSMutableURLRequest(URL: url)
    let session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    // Verify downloading data is allowed
    do {
        request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
    } catch let error as NSError {
        print("Error in request post: \(error)")
        request.HTTPBody = nil
    } catch {
        print("Catch all error: \(error)")
    }

    // Post the data
    let task = session.dataTaskWithRequest(request) { data, response, error in
        completionHandler(data: data, response: response, error: error)

        // Stop download indication
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false // Stop download indication

    }

    task.resume()

}
26.06.2015
  • Это очень полезно, но предположим, что bodyData — это {имя: Профессор Дамблдор, тип: Волшебник} Как мне преобразовать это в строку? В нем много кавычек, но я не уверен, как отформатировать его как строку. 26.06.2015
  • Сотрите последний комментарий, я только что понял: name=Professor Dumbledore&Type=Wizard 26.06.2015
  • Рад видеть, что вы поняли это - удачного кодирования и хороших вам выходных! 26.06.2015
  • @FelipeCaldas Смотрите ответ выше 14.11.2015

  • 2

    Swift 3 и выше

    ПОЛУЧИТЬ

    private func httpRequest() {
    
        //create the url with NSURL
        let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! //change the url
    
        //create the session object
        let session = URLSession.shared
    
        //now create the URLRequest object using the url object
        let request = URLRequest(url: url)
    
        //create dataTask using the session object to send data to the server
        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
    
            guard error == nil else {
                return
            }
    
            guard let data = data else {
                return
            }
    
            do {
                //create json object from data
                if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                    print(json)
                }
            } catch let error {
                print(error.localizedDescription)
            }
        })
        task.resume()
    }
    

    РАЗМЕСТИТЬ

    @IBAction func submitAction(sender: AnyObject) {
    
        //declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid
    
        let parameters = ["name": nametextField.text, "password": passwordTextField.text] as Dictionary<String, String>
    
        //create the url with URL
        let url = URL(string: "http://myServerName.com/api")! //change the url
    
        //create the session object
        let session = URLSession.shared
    
        //now create the URLRequest object using the url object
        var request = URLRequest(url: url)
        request.httpMethod = "POST" //set http method as POST
    
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) // pass dictionary to nsdata object and set it as request body
    
        } catch let error {
            print(error.localizedDescription)
        }
    
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
    
        //create dataTask using the session object to send data to the server
        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
    
            guard error == nil else {
                return
            }
    
            guard let data = data else {
                return
            }
    
            do {
                //create json object from data
                if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                    print(json)
                    // handle json...
                }
    
            } catch let error {
                print(error.localizedDescription)
            }
        })
        task.resume()
    }
    
    11.12.2016
  • Спасибо, что поделились Сухитом! Я настоятельно рекомендую поместить это как общую функцию с переданными ей URL-адресом и параметрами. Затем может быть обработчик, чтобы разработчик мог обрабатывать исключения/данные при вызове функции. Обновлю свой ответ, чтобы он содержал то же самое. 28.01.2017

  • 3
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { return }
    
        let session = URLSession.shared
        session.dataTask(with: url) { (data, response, error) in
            if let response = response {
                print(response)
            }
    
            if let data = data {
                print(data)
                do {
                    let json = try JSONSerialization.jsonObject(with: data, options: [])
                    print(json)
                } catch {
                    print(error)
                }
    
            }
        }.resume()
    }
    

    Это метод получения.

    12.03.2018

    4

    Этот метод вызывает http-запрос.

    String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) 
    

    Потому что Swift String не имеет такой подписи инициализации.

    Этот метод будет написан где-то в проекте, как extension из String

    Это было бы что-то вроде этого

    extension String{
        init(contentsOfURL: NSURL, encoding: NSUTF8StringEncoding, inout error: NSError){
            // load data from url
            self = //parse data to string
        }
    }
    
    26.06.2015
  • Однако у меня нет расширения, написанного для String. Это встроено в SDK? 26.06.2015
  • Любая идея, как сделать запрос POST с этим? 26.06.2015
  • Ты можешь это сделать. см. этот stackoverflow.com/questions /26364914/ 26.06.2015

  • 5

    Инициализатор String(contentsOfUrl:encoding:error) незаметно выполняет запрос GET и возвращает содержимое в виде строки с указанной кодировкой.

    Один из способов сделать запрос — создать NSURLConnection и использовать NSMutablrURLRequest, чтобы установить HTTP-метод post. С помощью NSMutableURLRequest вы можете создать NSURLConnection и сразу же запустить его с помощью делегата или вызвать NSURLConnection.sendSynchronousRequest или NSURLConnection.sendAsynchronousRequest для отправки запроса.

    26.06.2015

    6
    let parameters = ["username": "@Bipin_kumar", "tweet": "HelloWorld"]
    
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else { return }
    request.httpBody = httpBody
    
    let session = URLSession.shared
    session.dataTask(with: request) { (data, response, error) in
        if let response = response {
            print(response)
        }
    
        if let data = data {
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: [])
                print(json)
            } catch {
                print(error)
            }
        }
    
    }.resume()
    

    Это почтовый метод.

    12.03.2018

    7

    GET-запрос

     func getRequest(with url: URL, callback: @escaping (Any?) -> Swift.Void) -> Void {
    
        let defaultConfigObject = URLSessionConfiguration.default
        defaultConfigObject.timeoutIntervalForRequest = 30.0
        defaultConfigObject.timeoutIntervalForResource = 60.0
    
        let session = URLSession.init(configuration: defaultConfigObject, delegate: nil, delegateQueue: nil)
    
        var urlRequest = URLRequest(url: url as URL)
        urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
    
        urlRequest.httpMethod = "GET"
        session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
    
            guard    let httpResponse: HTTPURLResponse = response as? HTTPURLResponse
                else {
                    print("Error: did not receive data")
                    return
                  }
    
            var response : (Any)? = nil
    
            if httpResponse.statusCode == 200 {
                print(httpResponse)
    
                guard let responseData = data else {
                    print("Error: did not receive data")
                    return
                }
    
                do {
                    let responseData = try JSONSerialization.jsonObject(with: responseData, options: [JSONSerialization.ReadingOptions.allowFragments])
    
                      response = responseData
                     callback(response)
                }
                catch _ as NSError {
    
                    let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                    callback(responseString)
                    return
                }
            }
            else {
                print(httpResponse)
    
                guard error == nil else {
                    print("error calling GET on /todos/1")
                    print(error ?? "error")
                    callback(response!)
                    return
                }
    
            }
        }).resume()
    }
    

    ОТПРАВИТЬ ЗАПРОС

    //MARK: post request
    func postRequest(with url:URL, postBody:String, callback: @escaping (Any?) -> Void) -> Void {
    
        let defaultConfigObject = URLSessionConfiguration.default
        defaultConfigObject.timeoutIntervalForRequest = 30.0
        defaultConfigObject.timeoutIntervalForResource = 60.0
    
        let session = URLSession.init(configuration: defaultConfigObject, delegate: nil, delegateQueue: nil)
    
        let params: String! = postBody
    
        var urlRequest = URLRequest(url: url as URL)
        urlRequest.httpMethod = "POST"
    
        let data = params.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
        urlRequest.httpBody = data
    
        session.dataTask(with: urlRequest, completionHandler: { (data, urlResponse, error) in
    
    
            guard let httpResponse:HTTPURLResponse = urlResponse as? HTTPURLResponse
                else{
                    print("did not get any data")
                    return
                }
            var response : (Any)? = nil
    
            if httpResponse.statusCode == 200 {
    
                guard let responseData = data else {
                    print("Error: did not receive data")
                    return
                }
    
                do {
                    guard let responseData = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
                        print("error trying to convert data to JSON")
                        return
                    }
    
                    response = responseData
                    callback(response)
                } catch _ as NSError {
    
                    let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                    callback(responseString)
                    return
                }
            }
    
            else {
            guard error == nil else {
                print("error calling GET on /todos/1")
                print(error ?? "error")
                callback(nil)
                return
            }
        }
        }).resume()
    }
    

    Всегда старайтесь проверять код HTTPURLResponse

    17.05.2018
    Новые материалы

    Получение стоковых обновлений с помощью Python
    Для начинающего финансового аналитика Введение Описание: Этот проект Python создает скрипт для получения текущих обновлений акций с финансового веб-сайта Yahoo. Для этого проекта мы..

    Это все, что вам нужно знать о Kotlin в 2022 году
    Добро пожаловать! Kotlin — это язык программирования, популярность которого, кажется, растет, его действительно можно использовать для создания чего угодно, и если вы хотите узнать о Kotlin,..

    Текстовый графический интерфейс с Lanterna на Java
    Мой опыт работы с компьютерами (и текстовыми графическими пользовательскими интерфейсами) начался еще в восьмидесятых, когда я был ребенком, на дне рождения друга. Это был «новенький» Amstrad..

    Перезарядите свой мозг: умопомрачительный потенциал мозговых компьютерных интерфейсов
    Способность читать свои мысли и управлять объектами разумом долгое время были предметом человеческого любопытства, ограниченного областью научной фантастики… то есть до сих пор? С технологией,..

    Основы C# — Нулевой оператор объединения (??)
    Оператор ?? называется null-coalescing operator . Этот оператор используется для предоставления значения по умолчанию, если значение операнда в левой части оператора равно null ...

    Сравнение номеров версий в C++ с использованием синтаксического анализа строк
    Номера версий обычно используются для обозначения развития или обновлений программного обеспечения или любого другого продукта. При работе с номерами версий в C++ может быть полезно сравнить две..

    В мир искусственного интеллекта…
    ИИ — это новое топливо в современном мире. Куда бы вы ни обратились, с кем бы вы ни разговаривали — они, как правило, упоминают об ИИ хотя бы раз в ходе разговора. ИИ гудит повсюду. У каждого..