Пример HTTP GET запроса в Swift

Перевод данной статьи

В этом swift уроке, вы изучите как отправлять HTTP GET запрос в swift. Вы также узнаете как установить параметры запросы и хедеры HTTP запросов и как читать HTTP ответ. Обобщая, этот урок затронет:

  • Отправку HTTP GET запроса
  • Отправку HTTP хедеров запроса
  • Чтение HTTP статуса ответа
  • Чтение HTTP пришедших хедеров
  • Чтение HTTP ответа тела
  • Конвертация JSON HTTP ответа в Swift структуру

Общедоступный Веб сервис RESTful

В этом уроке, я буду использовать общедоступный и бесплатный на момент написания этого уроке веб сервис RESTfull: https://jsonplaceholder.typicode.com. Этот веб сервис позволяет мне отправлять HTTP запросы к нему и получать обратно ответ в виде JSON. На пример, если я открою следующую url в браузере: https://jsonplaceholder.typicode.com/todos/1 то я получу следующий JSON документ:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
} 

Отправка HTTP GET запроса

Ниже очень простой пример того как можно отправить HTTP GET запрос в Swift. Пожалуйста обратите внимание на комментарии в коде.

// Create URL
let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")
guard let requestUrl = url else { fatalError() }
// Create URL Request
var request = URLRequest(url: requestUrl)
// Specify HTTP Method to use
request.httpMethod = "GET"
// Send HTTP Request
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
    
    // Check if Error took place 
    if let error = error {
        print("Error took place \(error)")
        return
    }
    
    // Read HTTP Response Status code 
    if let response = response as? HTTPURLResponse {
        print("Response HTTP Status code: \(response.statusCode)")
    }
    
    // Convert HTTP Response Data to a simple String 
    if let data = data, let dataString = String(data: data, encoding: .utf8) {
        print("Response data string:\n \(dataString)")
    }
    
}
task.resume()

Отправка хедеров в HTTP запросе

Если вам необходимо содержать в HTTP запросе конкретные хедеры, тогда ниже есть приме как вы можете это сделать.

var request = URLRequest(url: requestUrl)
request.httpMethod = "GET"
// Set HTTP Request Header
request.setValue("application/json", forHTTPHeaderField: "Accept")

Вы можете установить более чем один хедер.

request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Basic htu574kfj584kfnd84kdlwut92jayebgpylg8md72msgrk", forHTTPHeaderField: "Authorization")

Чтение хедеров HTTP ответа

Как только вы получите HTTP ответ, вы можете прочитать из HTTPURLResponse объекта все HTTP хедеры в ответе за раз или если вы знаете хедеры запроса HTTP, то вы можете прочитать значение каждого указанного хедера.

Чтение всех полей хедеров

let allHeaderFields:[AnyHashable : Any] = response.allHeaderFields
print("All headers: \(allHeaderFields)")

Чтение конкретных хедеров

let contentTypeHeader = response.value(forHTTPHeaderField: "Content-Type")

и здесь то, как вы можете начать использовать HTTP ответ, когда получите его:

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
 
    if let response = response as? HTTPURLResponse {
        // Read all HTTP Response Headers
        print("All headers: \(response.allHeaderFields)")
        // Read a specific HTTP Response Header by name
        print("Specific header: \(response.value(forHTTPHeaderField: "Content-Type") ?? " header not found")")
    }
     
}
task.resume()

Чтение тела HTTP ответа

Когда HTTP ответ получен, вы вероятно хотите прочитать его HTTP тело. Используйте фрагмент кода ниже для конвертации ответа HTTP тела/даты в человеколюбий читаемые строковые значения.

if let data = data, let dataString = String(data: data, encoding: .utf8) {
    print("Response data string:\n \(dataString)")
}

ниже выглядит код если вы используете URLSession dataTask:

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
  
    if let data = data, let dataString = String(data: data, encoding: .utf8) {
        print("Response data string:\n \(dataString)")
    }
    
}
task.resume()

Конвертирование даты в словарь

Если выше HTTP GET запрос вызван, то тело ответа будет содержать строковый JSON который можно легко конвертировать в словарь. Здесь как полученный строковый JSON выглядит:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Давайте сейчас конвертируем его в Swift словарь:

do {
           if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
                
                // Print out entire dictionary
                print(convertedJsonIntoDict)
                
                // Get value by key
                let userId = convertedJsonIntoDict["userId"]
                print(userId ?? "userId could not be read")
                
            }
 } catch let error as NSError {
            print(error.localizedDescription)
  }

Конвертация даты в Swift структуру

Мы так же можем конвертировать объект даты в Swift структуру. Для этого мы должны создать Swift структуру которая содержит имена полей которые совпадают с JSON. Вот как выглядит строка JSON из тела ответа. При чтении из ответа HTTP приведенная ниже строка JSON имеет форму данных:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Вот как должна выглядеть наша Swift структура

struct ToDoResponseModel: Codable {
    let userId: Int
    let id: Int
    let title: String
    let completed: Bool
}

Вот как выглядит конвертация даты в Swift структуру

func parseJSON(data: Data) -> UserResponseModel? {
    
    var returnValue: UserResponseModel?
    do {
        returnValue = try JSONDecoder().decode(UserResponseModel.self, from: data)
    } catch {
        print("Error took place\(error.localizedDescription).")
    }
    
    return returnValue
}

Давайте все соединим вместе

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
   
        guard let data = data else { return }
        // Using parseJSON() function to convert data to Swift struct
        let todoItem = parseJSON(data: data) 
            
        // Read todo item title
        guard let todoItemModel = todoItem else { return }
        print("Todo item title = \(todoItemModel.title)")
 
 }
task.resume()

Я надеюсь этот урок был полезен для вас. Проверьте другие Swift уроки на этом сайте и вы найдете много полезного кода и примеров.