[SwiftUI] CryptoApp: Data Modeling 2

Junyoung Park·2022년 11월 4일
0

SwiftUI

목록 보기
88/136
post-thumbnail

Download coin details by creating a data model, view model, and API request | SwiftUI Crypto App #19

CryptoApp: Data Modeling 2

구현 목표

  • 디테일 뷰에 사용할 데이터 모델링

구현 태스크

  • API를 통한 코인 디테일 데이터를 패치하는 데이터 서비스 클래스 구현
  • 데이터 서비스 클래스가 리턴받은 데이터 퍼블리셔를 구독하는 뷰 모델 구현
  • 디테일 뷰 이니셜라이즈 단에서 해당 뷰 모델을 초기화

소스 코드

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?
}
  • API를 통해 받아올 데이터
  • JSON 파싱을 위한 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를 초기화하는 방법으로 뷰 모델 이니셜라이즈

구현 화면

profile
JUST DO IT

0개의 댓글