์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
- SwiftUI
- swift
- Kuring
- TCA
- ํจ์คํธ์บ ํผ์ค
- node.js
- reactorkit
- designpattern
- CollectionView
- Swfit
- rxcocoa
- ios
- realm
- SnapKit
- visionOS
- Xcode
- combine
- Lv2
- tableView
- BFS
- ๋ฐฑ์ค
- MVVM
- UIKit
- ํ๋ก๊ทธ๋๋จธ์ค
- arkit
- RxSwift
- Flutter
- raywenderlich
- XCTest
- BOJ
- Today
- Total
lgvv98
๐ผ ch15 ๊ฒ์์ ์ด์ฉํด ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ํ์ฑ๊น์ง! ๋ณธ๋ฌธ
๐ผ ch15 ๊ฒ์์ ์ด์ฉํด ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ํ์ฑ๊น์ง!
๐ฅ ์บ๋ฟ๋งจ 2021. 6. 29. 11:28โ ์ด๋ฒ์๊ฐ์๋ ์๋ฒ์์ API๋ฅผ ๋ฐ์์์ ํ์ฑ๊น์ง ํ๋ ๊ฒ์ ์์๋ณด์!
โ ์ด๋ฒ์๊ฐ์ ์์๋ณผ ์ฝ๋๋ ์๋์ ๊ฐ์ ์ฝ๋์ด๋ค.
class SearchAPI {
static func search(_ term: String, completion: @escaping ([Movie]) -> Void) { // completion ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๋ฐฉ๋ฒ
// ์ด์ค์ผ์ดํ์ด ์์ผ๋ฉด ํจ์๊ฐ ์ข
๋ฃ๋๊ณ ๋์ ์คํ
let session = URLSession(configuration: .default) // 1. ์ธ์
๋ง๋ค๊ธฐ
var urlComponents = URLComponents(string: "https://itunes.apple.com/search?")!
let mediaQuery = URLQueryItem(name: "media", value: "movie")
let entityQuery = URLQueryItem(name: "entity", value: "movie")
let termQuery = URLQueryItem(name: "term", value: term)
urlComponents.queryItems?.append(mediaQuery)
urlComponents.queryItems?.append(entityQuery)
urlComponents.queryItems?.append(termQuery)
let requestURL = urlComponents.url! // 2. url ๊ตฌ์ฑ
let dataTask = session.dataTask(with: requestURL) { data, response, error in
let successRange = 200..<300
guard error == nil,
let statusCode = (response as? HTTPURLResponse)?.statusCode,
successRange.contains(statusCode) else {
// ์๋ฌ๊ฐ ์๊ณ , ์ํ์ฝ๋์ ์๋ต์ ๋ํ HTTPURLResponse์์ ์ฐพ์ ํ ๋นํ๊ณ , ์ํ์ฝ๋๊ฐ ๋ฒ์ ์์ ํฌํจ๋๋ค๋ฉด ์ค๋ฌด์คํ๊ฒ ๋์ด๊ฐ๊ณ
// ๊ทธ๋ ์ง ์์ผ๋ฉด completion์ ๋น ๋ฐฐ์ด์ ์ค๋ค
completion([]) // completion๋ถ๋ถ์ ์๋ฌด๊ฒ๋ ์ ๋ณด๋ฅผ ๋ด์ง ์๋๋ค.
return
}
guard let resultData = data else {
// ์์ error์ด ์๋๊ฑธ ํ์ธํ๊ณ , dataTask์ data๋ฅผ ๊ฒฐ๊ณผํ
์ดํฐ ๋ณ์์ ๋์
ํ๋๋ฐ, ์ด ์์
์ด ์คํจํ๋ฉด completion์ ๋น๋ฐฐ์ด ์ฃผ๊ณ ๋ฆฌํด
completion([])
return
}
let movies = SearchAPI.parseMovies(resultData) //
completion(movies)
}
dataTask.resume() // 3. resume์ผ๋ก ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
}
static func parseMovies(_ data: Data) -> [Movie] { // ํ์
๋ฉ์๋๋ก ์ ์ธ
let decoder = JSONDecoder() // 1. ๋์ฝ๋ ์ ์ธํ๊ณ
do {
let response = try decoder.decode(Response.self, from: data) // data๋ก๋ถํฐ Responseํ์
์ผ๋ก ๋์ฝ๋ฉ!
let movies = response.movies
return movies
} catch let error {
print("--> parsing error: \(error.localizedDescription)")
return []
}
}
}
struct Response: Codable {
let resultCount: Int
let movies: [Movie]
enum CodingKeys: String, CodingKey {
case resultCount
case movies = "results"
}
}
struct Movie: Codable {
let title: String
let director: String
let thumbnailPath: String
let previewURL: String
enum CodingKeys: String, CodingKey {
case title = "trackName"
case director = "artistName"
case thumbnailPath = "artworkUrl100"
case previewURL = "previewUrl"
}
}
์ฐ์ search ์ชฝ์์ URL ์ธ์ ์ ํตํด ๊ตฌ์ฑํ๋ ๋ชจ์ต์ ๋ณผ ์ ์์ด.
๊ทธ ๋ค์์ dataTask ์ชฝ์ธ๋ฐ ๋ณผ๊น?
์ฐ์ successRange๋ HTTP ์๋ต์ฝ๋์์ 200๋ฒ๋๊ฐ ์ฑ๊ณต์ ์ธ ์๋ต์ด๋ผ์ ์ ๋ ๊ฒ ๋ฒ์๋ฅผ ์ ํ๊ฑฐ์ผ.
๊ทธ ๋ค์์๋ ์๋ฌ๊ฐ ์๊ณ , ์๋ต์ฝ๋๊ฐ ์ฑ๊ณต์ ์ธ ๋ฒํธ์ ์ํ๋ฉด guard ๋ฌธ์ ์ง๋๊ฐ์ผ๊ฒ ์ง?
๊ทธ ๋ค์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ์์ ๋์ ํด์ ๊ทธ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ๋ ํจ์๋ก ๋ณด๋ด์ฃผ๋ฉด ๋ผ.
๊ทธ ๋ค์์ parseMovie ์ชฝ์ธ๋ฐ ์คํํฑ ๋ฉ์๋๋ผ ์ธ์คํด์ค(๊ฐ์ฒด)๋ฅผ ์์ฑํ์ง ์์๋ ๋ผ.
โ๏ธ ๊ทธ๋ฆฌ๊ณ ์ ์ผ ์ค์ํ๊ฒ resume ๊ผญ ์์ฑํด์ค์ผ ์ฝ๋๊ฐ ์๋ํ๋๊น.. ์์ง๋ง๊ธฐ!
โ parseMovie ์ชฝ์ด ์ด์ ์ง์ง parsing ๋ถ๋ถ์ด์ผ.
1. ๋ฐํํ ๋ฐ์ดํฐ ํ์ ์ ๋ช ์ํ๊ณ ( ํจ์ ์ ์ธ๋ถ์ )
2. JSONDecoder๋ฅผ ๋์ ํ๊ณ ( JSON ํ์ผ ๋์ฝ๋ฉ ํ ์์ ์ด๋ผ์ )
3. decoder.decode๋ฅผ ํตํด ํ์ฑ์ ์ด๋ป๊ฒ ํ ๊ฑด์ง ๊ฐ๋ตํ๊ฒ ์ ํด์ฃผ๋๋ฐ ( try๋ฅผ ์ฌ์ฉํ๋๊ฑด ์ด์ ๋ ์ด ์์ ์ด ์คํจํ ์๋ ์๊ธฐ ๋๋ฌธ์ )
--> ์คํจํ๋ฉด catch๋ก ์ด๋
decode์ ํ๋ผ๋ฏธํฐ์ ๋ํด์ ์์๋ณด๋ฉด
์ฒซ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ ์ด๋ค ํ์์ผ๋ก ๋ฐ๊ฟ๊ฑด๊ฐ
๋๋ฒ์งธ ํ๋ผ๋ฏธํฐ(from)๋ ๋ฐ๊ฟ ๋ฐ์ดํฐ๋ ์ด๋ค๊ฑด์ง
์ฆ from A to B (A์์๋ถํฐ B๋ก) ์ ์๋ฏธ๋ก ์๊ฐํด๋ณด๋ฉด ์ดํด๊ฐ ์ฝ๋ค.
4. ์ฐ๋ฆฌ๊ฐ ํ์ํ๊ฑด movies์ธ๋ฐ, ์๋ต๋ฐ์์จ๊ฑฐ๋ฅผ ๋ค ์ฐ๋๊ฒ ์๋๋ผ, ๊ทธ ์ค์์ movies์ ๋ํ ์ ๋ณด๋ง ํ์ํจ์ผ๋ก ๊ทธ์ ๋ง๊ฒ๋ ๋ณํํด์ค ๋ชจ์ต์ด์ผ.
๐ก ๋ด๊ฐ ์์์์ ์ฌ์ฉํ ๋ฐ์ดํฐ์์ JSON ํธ๋ฆฌ ๊ตฌ์ฑ๋๊ฑธ ์ฐธ๊ณ ํ์ฌ ์ฌ์ฉํ์๋ค.
5. ์ฐ๋ฆฌ๊ฐ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ movies์ ํํ๋ก ๋ฆฌํด!
var movies: [Movie] = [] // ๋ค๋ฅธ viewController์์ ์ ์ธ๋์ด ์๋ ํํ
์์ ์ด๋ฐ ์์ผ๋ก ์ ์ธ๋์ด ์๋ค!
โ CodingKey ์ ๋ถ๋ถ์ Codable์ ์ฌ์ฉํ ๋, ์๋ฒ์์ ๋ด๋ ค์ค key์ ์ฐ๋ฆฌ๊ฐ ์ ์ธํ ๋ณ์๋ช ์ด ๊ฐ์์ผ๋ง ์๋ฌ๊ฐ ๋์ง ์๋๋ฐ, ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ณ์๋ช ์ผ๋ก ๋ฐ๊ฟ์ค ๋ ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ค.
โ๏ธ ์ฝ๋ฉํค ์ชฝ์ s ์๋ชป ๋ถ์ฌ์ ์๋ฌ ๋ง์ด ๋ด๋๋ฐ,,, ์ด๊ฑฐ ์ค์ค๋ก ์ฃผ์ํ์...
(์ถ๊ฐ)
JSONSerializaition์ ์ฐ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, ์ฌ๊ธฐ ์์ ์์๋ JSON์์ ํ๋์ key:value๋ง ํ์ํ๋๊น ์ด๊ฒ ํ์ ์์์ง๋ง ๋ง์ฝ JSON์ ๋์ ๋๋ฆฌ ํํ๋ก ๋ณํํด์ ์ฌ๋ฌ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐฐ์ด์์ผ๋ก ๊ด๋ฆฌํด์ผํ๋ฉด ์ด ์ฝ๋๊ฐ ๊ผญ ๋ค์ด๊ฐ์ผํ๋ค.
์ด์ ๋ํ ๋ถ๋ถ์ด ํฌ์คํ ์ ์ฐธ๊ณ ํ๊ธฐ
'โ ๏ธ deprecated โ ๏ธ > ํจ์บ (์ฌ์ธ์)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ฌ ch17 Netflix ํ์ฅ์ฑ ์ฝ๋๋ฆฌ๋ทฐ(firebase, kingfisher) + ch15 (0) | 2021.07.05 |
---|---|
ch17 ๋์ ScrollView Guide! ์ํ์ข์ฐ!! (0) | 2021.06.29 |
ch15 escaping๊ณผ non-escaping ํด๋ก์ ์ ๋ํด์ ์์๋ณด์ (0) | 2021.06.29 |
๐ ch15 ์ธ์คํด์ค ๋ฉ์๋ vs ํ์ ๋ฉ์๋ (0) | 2021.06.29 |
๐ก ch14 URLSession (feat. Codable) (0) | 2021.06.28 |