본문 바로가기

Ios

Ios - Api 사용하기(urlSession, parseJson)

Ios에서 네트워크 통신을 하기 위해 urlSession이라는 클래스를 사용합니다.

 

urlSession은 서버에 요청을 보내기 위해 사용하는 클래스이며 자료를 업로드하고 다운로드하는데 필요한, 완전한 형태의 ios 네트워크 API입니다.

 

urlSession을 이용한 네트워크 통신에서는 아래와 같은 5가지의 기본 단계가 필요합니다.

 

		//0. API를 사용할 url 주소가 있어야합니다.
let urlString: String = "https://api.test.com/data/person?n=1&a=22"

func performRequest(with urlString: String){

		// 1. url주소를 인자로 전달한 URL 구조체를 만듭니다.
        if let url = URL(string: urlString) {
            
		// 2. URL Session을 만듭니다.
            let session = URLSession(configuration: .default)
            
        // 3. session에 task을 부여합니다.
            let task = session.dataTask(with: url) { (data, response, error) in
                if error != nil { // error가 비어있지(nil) 않다면
                    self.delegate?.didFailWithError(error: error!)
                    return
                }
                
                if let safeData = data {
                    if let weather = self.parseJSON(safeData){
                        self.delegate?.didUpdateWeather(self, weather: weather)
                    }
                }
            }
            
          // 4. task를 실행합니다.
            task.resume()
        }
    }

didUpdateWeather와 didFailWithError는 네트워크 요청을 통해 전달받은 데이터(여기서는 json형식의 데이터), 또는 에러를 delegate로 처리하기 위해 프로토콜로 선언한 메소드입니다. 

 

이 예제에서 사용한 api을 통해 전달받은 데이터는 Json 형식의 파일이므로 이것을 앱에서 알맞게 사용하기 위해서는 파싱(parsing)과정이 필요합니다. Json을 parsing하는 메소드인 parseJSON은 아래와 같습니다.

(tip) api를 통해 json 형식의 Data타입 파일을 받고 parsing전에 확인해보고 싶을 때 아래의 코드를 이용해도 됩니다.

let dataString = String.init(data: apiData, encoding: .utf8)

 

핵심! decoder.decode(WeatherData.self, from weatherData)의 뜻 = decoder야 api로 부터 받아온 json 파일인 weatherData로부터 WeatherData의 객체형태로 디코드해줘!

// API를 통해 받은 데이터를 인자로 전달하여 파싱의 과정을 거친 뒤, 앱의 데이터 모델인 WeatherModel형식으로 반환받는 메소드이다.
func parseJSON(_ weatherData: Data) -> WeatherModel? {

		//1. JSON 디코더 인스턴스를 생성한다. 이것을 통해 파싱을 수행한다.
        let decoder = JSONDecoder()
        
        do {
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData) // 2. JSON파일에서 파싱하고 싶은(골라내고 싶은) 쌍 데이터만 추출하도록 구조체 파일을 정의한뒤 인자값으로 전달한다.
            let id = decodedData.weather[0].id
            let temp = decodedData.main.temp
            let name = decodedData.name
            
            let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp) // 3. 앱에서 사용할 모델에 맞게 파싱한 값으로 새 모델 데이터를 만든다.
            return weather
        } catch {
            delegate?.didFailWithError(error: error) // 파싱이 실패했을 경우 호출
            return nil
        }
    }

 

파싱할 자료들을 골라 놓은 것이라 생각하면 된다. json 객체는 struct 키워드를 통해 구조체로 구현하면 되고 Encodable 프로토콜과 Decodable 프로토콜을 동시에 의미하는 Codable을 통해 두 프로토콜을 각각에 구조체에 선언해줘야한다.

// JSON DATA 전체를 나타냄. json data는 곧 json 객체 형태이다. 그리고 json객체에 속하는 쌍들을 가지고 있다.
struct WeatherData: Codable {
    let name: String
    let main: Main //json 객체의 쌍의 값이 json 객체를 가지고 있는 경우
    let weather: [Weather] //json 객체의 쌍의 값이 json객체의 배열을 가지고 있는 경우
}

struct Main: Codable {
    let temp: Double
}

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

 

API로 받은 JSON DATA