티스토리 뷰
URLSession
- ViewController
import UIKit
class ViewController: UIViewController {
let temperatureLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
NetworkService.shared.fetch(urlString: URL.weather) { weatherInfo in
self.temperatureLabel.text = String(weatherInfo.main.temp)
}
}
}
//MARK: -UI
extension ViewController {
final private func configureUI() {
setAttributes()
setConstraints()
}
final private func setAttributes() {
temperatureLabel.text = "0"
}
final private func setConstraints() {
view.addSubview(temperatureLabel)
temperatureLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
temperatureLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
temperatureLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}
- Model
import Foundation
struct WeatherInfo: Codable {
let main: Main
let weather: [Weather]
struct Main: Codable {
let temp: Double
}
struct Weather: Codable {
let main: String
}
}
- Service
import Foundation
// singleton으로 사용
class NetworkService {
static let shared = NetworkService()
func fetch(urlString: String, completion: @escaping (WeatherInfo)-> Void) {
URLSession.shared.dataTask(with: URL(string: urlString)!) { data, response, error in
// 1. error가 있다면
guard error == nil else { fatalError() }
// 2. response가 있으면서 응답 코드가 200 ~ 400 사이일 때 (응답이 성공했을 때)
guard let response = response as? HTTPURLResponse, (200..<400).contains(response.statusCode) else { fatalError() }
// 3. data가 있다면
guard let data = data else { return }
do {
let decodedData = try JSONDecoder().decode(WeatherInfo.self, from: data)
DispatchQueue.main.async {
// UI에 대한 작업이기 때문에 main thread에서 해줘야 함.
// main에서는 항상 async만 써야 함 (sync X)
print(Thread.isMainThread) // true
completion(decodedData)
}
} catch {
fatalError()
}
}.resume()
}
private init() {}
}
extension URL {
static let weather = "https://api.openweathermap.org/data/2.5/weather?q=seoul&appid"
}
1. 응답(response)는 HTTPURLResponse로 타입캐스팅 해줘야 함
guard let response = response as? HTTPURLResponse else { fatalError() }
2. 응답(response)이 성공일 경우에만 data 받아옴
guard let (200..<400).contains(response.statusCode) else { fatalError() }
3. 해당 thread가 메인 thread인지 확인하는 방법
print(Thread.isMainThread)
4. URLSession은 비동기적으로 일어나기 때문에 @escaping처리가 필요
func fetch(urlString: String, completion: @escaping (WeatherInfo)-> Void) { }
'순진이의 하루 > study정리' 카테고리의 다른 글
12. Collapsed TableView, InfiniteScrollView_2022.09.14 (0) | 2022.09.19 |
---|---|
11. Result Type_2022.09.07 (0) | 2022.09.19 |
8. 고차함수, UIViewPropertyAnimator_2022.08.29 (0) | 2022.08.29 |
7. UserDefaults, Animation_2022.08.24 (0) | 2022.08.24 |
6. CollectionView code로 짜기, Delegate Pattern_2022.08.22 (0) | 2022.08.22 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크