[iOS] - URLSession 으로 API 호출해서 데이터 받기

sun02·2022년 2월 21일
1

iOS

목록 보기
9/27

URLSession Life Cycle에 맞춰 https://home.openweathermap.org 에서 제공하는 데이터를 받아 앱에 보여주는 코드를 작성해보겠습니다

URLSession과 HTTP에 관한 기본 설명은 [iOS] - URLSession, HTTP 여기서 볼 수 있습니다.

- URLSession Life Cycle

  1. session configuration 결정, session 생성
  2. 통신할 URL, Request 객체 설정
  3. 사용할 task 결정, 그에 맞는 completionHandler나 delegate 메소드 작성
  4. task 실행, task 완료 후 completion Handler 클로저 호출

1. Session configuration 결정, Session 생성

let session = URLSession(configuration: .default)
  • URLSession의 종류 (공유, 기본, 임시, 백그라운드) 중 기본세션으로 session을 생성하였습니다.

2. 통신할 URL, Request 객체 설정

- url 설정

guard let url = URL(String: "API주소") else { return }


제가 호출하고자하는 API는 다음과 같이 구성되어 있기 때문에

guard let url = URL(String: "https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&appid=개인APIKey") else { return }

위와 같이 작성해 주었습니다

- 데이터 객체 생성하기

위 API를 호출하는 경우 다음과 같은 JSON파일을 받게 되는데
이 파일 중 weather, main, name 데이터만 필요하기 때문에 위 세 타입을 받는 객체(weatherInformation)를 생성해야합니다.

1) weatherInformation.swift 파일 생성

2) weatherInformation struct 만들기

struct WeatherInformation: Codable {
    let weather: ?
    let main: ?
    let name: String
}
  • name은 string 타입이지만 weather과 main은 여러 데이터타입을 포함하고 있는 다른 타입이기 때문에 이 두 데이터 타입을 받을 객체를 따로 생성해주어야합니다
  • Codable = decodable + encodable으로 JSON을 인코딩, 디코딩 둘 다 가능하게 해주는 프로토콜입니다.

- weather struct 만들기

struct Weather: Codable {
    let id: Int
    let main : String
    let description: String
    let icodn: String
}

- temp struct 만들기

struct Temp: Codable {
   let temp: Double
   let feelsLike: Double
   let minTemp: Double
   let maxTemp: Double
   
     // Json 파일에 있더라도 사용하지 않는다면 정의해주지 않아도 됩니다.
    //let pressure: Int
    //let humidity: Int
    
     // 편의를 위해 구조체에서 json파일의 데이터 이름과 프로퍼티의 이름을 다르게 정의한 경우 다음과 같은 설정이 필요합니다.
    enum CodingKeys: String, CodingKey {
        case temp
        case feelsLike = "feels_like"
        case minTemp = "temp_min"
        case maxTemp = "temp_max"
    }
}
  • 일반적으로 프로퍼티의 이름을 JSON파일의 프로퍼티 이름과 같게 해주어야하지만, 다르게 정의하고 싶은 경우 위와 같이 codingkeys를 사용하여 설정해주면 됩니다.

- weatherInformation struct 완성

struct WeatherInformation: Codable {
    let weather: [Weather]
    let temp: Temp
    let name: String
    
    enum CodingKeys: String, CodingKey {
        case weather
        case temp = "main"
        case name
    }
}

3. 사용할 Task 설정, 그에 맞는 completionHandler나 delegate 메소드 작성하기

session.dataTask(with:url) { data, response, error in

}
  • 데이터 객체를 사용해서 데이터를 요청하고 받을 것이기 때문에 dataTask를 사용합니다.

API 호출에 성공하면 클로져의 data에 데이터가 들어가고, error는 Nil입니다.

session.dataTask(with: url) { data, response, error in

    guard let data = data, error == nil else { return } 

}

따라서 다음과 같이 optional 타입(Data?)인 data를 binding 할 수 있습니다.

4. task 실행, task 완료 후 completion Handler 클로저 호출

API호출에 성공하여 data에 데이터가 존재하는 경우,
미리 생성해놓은 WeatherInformation 타입으로 전달받은 데이터를 변환시켜야합니다.

JSON 데이터를 변환은 JSONdecoder객체를 사용하여 수행할 수 있습니다.

let decoder = JSONDecoder()

guard let weatherInformation = try? decoder.decode(WeatherInformation.self, from: data) else { return }

DispatchQueue.main.async {
    self?.weatherStackView.isHidden = false
    self?.configureView(weatherInformation: weatherInformation)
    }
  • decode에 실패하면 에러를 던져주기 때문에 try? 문을 사용합니다.
  • 전달받은 데이터를 바로 UI상으로 보여주기 때문에 DistpathQueue.main.async() 를 사용하여 UI 관련 작업을 메인스레드에서 실행하도록 해줍니다.
  • 클로져 마지막에 .resume() 메소드를 작성하여 작업을 실행시켜 줍니다.

- API 호출 메서드 전체

다음과 같이 URLSession을 사용하여 API를 호출하는 메서드가 완성되었습니다.

0개의 댓글