-
[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
'개발 > Swift' 카테고리의 다른 글
Combine Vs RxSwift (0) 2022.11.09 Apollo swift + Rxswift 를 활용한 API 네트워크와 에러처리 (0) 2022.11.03 [Swift] ViewController Custom Init (parameter 전달) (0) 2022.08.29 [Swift] 라이브러리 내부 이미지 관련 오류 (0) 2022.08.25 [Swift] 특정 코너만 CornerRadius 적용시키기 (0) 2022.08.22