ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] URLSession 통해 async fetch & json 파싱
    개발/Swift 2022. 10. 4. 09:01

    HTTP 메소드, JSON 파싱

    http 통신을 위해 URLSession을 사용해보고 얻어온 데이터를 원하는 정보만 디코딩해서 사용하려 한다.

    class Network {
        
        func fetchTrends() {
            guard let url = URL(string: "<https://api.giphy.com/v1/gifs/search?api_key=\\(apikey)>") else { return }
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            URLSession.shared.dataTask(with: request) { data, response, error in
                if let error = error {
                    print("Error fetch Trend", error.localizedDescription)
                }
                print(data)
            }
        }
    }
    

    우선 데이터 fetch를 위한 코드이다. dataTask 클로져 내에 data를 사용할 것이다.

    또 URLSession은 async await 을 지원해준다. 따라서 다음과 같이도 사용할수 있다.

    static func fetchTrends() async throws {
            guard let url = URL(string: "<https://api.giphy.com/v1/gifs/trending?api_key=\\(APIKEY)&offset=\\(offset)>") else {
                throw NetworkError.invalidURL }
            
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
             print("request \\(request)")
             
             
             let (data, response) = try await URLSession.shared.data(from: url)
             
            
             
        }
    

    let (data, response) = try await URLSession.shared.data(from: url) 해당 코드는 비동기로 처리가 된다. 그러므로 아래에 있는 코드는

    response를 받을떄까지 기다렸다가 처리된다.

    데이터는 아래와 같다. 나는 data-images-original & preview 에 있는

    height & width & url 이 필요한 상황이다.

    따라서 모델을 다음과 같이 정의했다.

    class GifData: Decodable {
        var data: [Gif]
    }
    
    class Gif : Decodable {
        var images: Images?
        
    }
    
    class Images: Decodable {
        var original: Image?
        var preview: Image?
        
        enum CodingKeys: String, CodingKey {
            case original       
    				case preview = "preview_gif"
        }
        
        required init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            original = try? values.decode(Image.self, forKey: .original)
            preview = try? values.decode(Image.self, forKey: .preview)
    
        }
    }
    
    class Image: Decodable {
        var url: String?
        var height: Int?
        var width: Int?
        
        enum CodingKeys: String, CodingKey {
            case url, mp4, height, width
        }
        
        required init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            url = try? values.decode(String.self, forKey: .url)
            width = try? Int(values.decode(String.self, forKey: .width))
            height = try? Int(values.decode(String.self, forKey: .height))
                             
        }
    }
    

    Decodable 한 모델을 통해 받아온 데이터를 모델링 할수 있다.

    let decoder = JSONDecoder()
    let gif = try decoder.decode(GifData.self, from: data)
    
    return gif.data
    

    전체 코드

    static func fetchTrends(offset: Int) async throws -> [Gif] {
            guard let url = URL(string: "<https://api.giphy.com/v1/gifs/trending?api_key=\\(APIKEY)&offset=\\(offset)>") else {
                throw NetworkError.invalidURL }
            
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
             
             let (data, response) = try await URLSession.shared.data(from: url)
             
             guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
                 throw NetworkError.invalidServerResponse
             }
             
             let decoder = JSONDecoder()
             let gif = try decoder.decode(GifData.self, from: data)
             return gif.data
             
        
    

    댓글

Designed by Tistory.