Download coins using a View Model and Data Service class | SwiftUI Crypto App #6
URLSession
데이터 퍼블리셔 사용@Published
구독coinSubscription = URLSession
.shared
.dataTaskPublisher(for: url)
.subscribe(on: DispatchQueue.global(qos: .default))
.tryMap { output -> Data in
guard
let response = output.response as? HTTPURLResponse,
response.statusCode >= 200 && response.statusCode < 300 else
{ throw URLError(.badServerResponse) }
return output.data
}
.receive(on: DispatchQueue.main)
.decode(type: [CoinModel].self, decoder: JSONDecoder())
.sink { [weak self] completion in
switch completion {
case .failure(let error):
print(error.localizedDescription)
self?.coinSubscription?.cancel()
case .finished: break
}
} receiveValue: { [weak self] coinModels in
self?.allCoins = coinModels
self?.coinSubscription?.cancel()
}
@Published
데이터에 해당 패치 데이터를 넣어주는 부분cointSubscription
의 타입은 AnyCancellable
옵셔널 타입으로 해당 구독을 이후 취소할 수 있음 private func addSubcriber() {
dataService
.$allCoins
.sink { [weak self] coinModels in
self?.allCoins = coinModels
}
.store(in: &cancellables)
}
store
로 구현import Foundation
import Combine
class CoinDataService {
@Published var allCoins: [CoinModel] = []
var coinSubscription: AnyCancellable?
init() {
fetchCoins()
}
private func fetchCoins() {
guard let url = URL(string: "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page=1&sparkline=true&price_change_percentage=24h") else { return }
coinSubscription = URLSession
.shared
.dataTaskPublisher(for: url)
.subscribe(on: DispatchQueue.global(qos: .default))
.tryMap { output -> Data in
guard
let response = output.response as? HTTPURLResponse,
response.statusCode >= 200 && response.statusCode < 300 else
{ throw URLError(.badServerResponse) }
return output.data
}
.receive(on: DispatchQueue.main)
.decode(type: [CoinModel].self, decoder: JSONDecoder())
.sink { [weak self] completion in
switch completion {
case .failure(let error):
print(error.localizedDescription)
self?.coinSubscription?.cancel()
case .finished: break
}
} receiveValue: { [weak self] coinModels in
self?.allCoins = coinModels
self?.coinSubscription?.cancel()
}
}
}
import Foundation
import Combine
class HomeViewModel: ObservableObject {
@Published var allCoins: [CoinModel] = []
@Published var portfolioCoins: [CoinModel] = []
private let dataService = CoinDataService()
private var cancellables = Set<AnyCancellable>()
init() {
addSubcriber()
}
private func addSubcriber() {
dataService
.$allCoins
.sink { [weak self] coinModels in
self?.allCoins = coinModels
}
.store(in: &cancellables)
}
}