Download coin details by creating a data model, view model, and API request | SwiftUI Crypto App #19
import Foundation
struct CoinDetailModel: Codable {
let id, symbol, name: String?
let blockTimeInMinutes: Int?
let hashingAlgorithm: String?
let description: Description?
let links: Links?
enum CodingKeys: String, CodingKey {
case id, symbol, name, links, description
case blockTimeInMinutes = "block_time_in_minutes"
case hashingAlgorithm = "hashing_algorithm"
}
}
struct Links: Codable {
let homepage: [String]?
let subredditURL: String?
enum CodingKeys: String, CodingKey {
case homepage
case subredditURL = "subreddit_url"
}
}
struct Description: Codable {
let en: String?
}
Codable
프로토콜에 따르는 구조체func fetchCoinDetails() {
guard let url = URL(string: "https://api.coingecko.com/api/v3/coins/\(coin.id)?localization=false&tickers=false&market_data=false&community_data=false&developer_data=false&sparkline=true") else { return }
coinDetailSubscription = NetworkingManager
.download(with: url)
.decode(type: CoinDetailModel.self, decoder: JSONDecoder())
.sink(receiveCompletion: NetworkingManager.handleCompletion,
receiveValue: { [weak self] coinDetails in
self?.coinDetails = coinDetails
self?.coinDetailSubscription?.cancel()
})
}
import Combine
class DetailViewModel: ObservableObject {
@Published var coinDetails: CoinDetailModel?
private let coinDetailDataService: CoinDetailDataService
private var cancellables = Set<AnyCancellable>()
init(coin: CoinModel) {
self.coinDetailDataService = CoinDetailDataService(coin: coin)
addSubscriber()
}
private func addSubscriber() {
coinDetailDataService
.$coinDetails
.sink { [weak self] coinDetails in
self?.coinDetails = coinDetails
}
.store(in: &cancellables)
}
}
init(coin: CoinModel) {
self.coin = coin
self._viewModel = StateObject(wrappedValue: .init(coin: coin))
}
StateObject
이기 때문에 WrappedProperty
를 초기화하는 방법으로 뷰 모델 이니셜라이즈