[SwiftUI] CryptoApp: List of Rows

Junyoung Park·2022년 11월 3일
0

SwiftUI

목록 보기
74/136
post-thumbnail
post-custom-banner

Add a dynamic List to display downloaded coins | SwiftUI Crypto App #5

CryptoApp: List of Rows

구현 목표

  • 동적 뷰 리스트 생성

구현 태스크

  • EnviornmentObject 생성
  • 뷰 모델 관리
  • 뷰 모델의 변수에 따른 UI 동적 관리

핵심 코드

import Foundation

class HomeViewModel: ObservableObject {
    @Published var allCoins: [CoinModel] = []
    @Published var portfolioCoins: [CoinModel] = []
    
    init() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.allCoins.append(DeveloperPreview.shared.coin)
            self.portfolioCoins.append(DeveloperPreview.shared.coin)
        }
    }
}
  • ObservableObject로 선언한 HomeViewModel
  • @Published 프로토콜을 따르는 allCoins, portfolioCoins 등 변수의 값의 변화를 뷰에서 감지 가능
  • 디스패치 큐를 통해 가데이터의 변경 상황을 알림
import SwiftUI

@main
struct CryptoAppBootCampApp: App {
    @StateObject private var viewModel = HomeViewModel()
    var body: some Scene {
        WindowGroup {
            NavigationView {
                HomeView()
                    .toolbar(.hidden)
            }
            .environmentObject(viewModel)
        }
    }
}
  • 전역 변수로 뷰 모델을 관리하기 위한 environmentObject
import SwiftUI

struct HomeView: View {
    @EnvironmentObject private var viewModel: HomeViewModel
    @State private var showPortfolio: Bool = false
...
  • 홈 뷰는 앱 최상단에서 내려받은 environmentObject를 관리하기 위해 @EnvironmentObject를 선언

소스 코드

 private var allCoinsList: some View {
        List {
            ForEach(viewModel.allCoins) { coin in
                CoinRowView(coin: coin, showHoldingsColumn: false)
                    .listRowInsets(.init(top: 10, leading: 0, bottom: 0, trailing: 10))
            }
        }
        .listStyle(.plain)
    }
  • 뷰 모델의 allCoins 데이터를 통해 동적 리스트를 그리는 UI
  • CoinRowView 뷰를 셀로 사용
private var portfolioCoinsList: some View {
        List {
            ForEach(viewModel.portfolioCoins) { coin in
                CoinRowView(coin: coin, showHoldingsColumn: true)
                    .listRowInsets(.init(top: 10, leading: 0, bottom: 0, trailing: 10))
            }
        }
    }
  • portfolioCoins 데이터를 활용
private var columnTitles: some View {
        HStack {
            Text("Coin")
            Spacer()
            if showPortfolio {
                Text("Holdings")
            }
            Text("Prices")
                .frame(width: UIScreen.main.bounds.width / 3.5, alignment: .trailing)
        }
        .font(.caption)
        .foregroundColor(Color.theme.secondaryText)
        .padding(.horizontal)
    }
  • 타이틀을 그리는 뷰
import SwiftUI

struct HomeView: View {
    @EnvironmentObject private var viewModel: HomeViewModel
    @State private var showPortfolio: Bool = false
    
    var body: some View {
        ZStack {
            // background layer
            Color.theme.background
                .ignoresSafeArea()
            
            // content layer
            VStack {
                homeHeader
                columnTitles
                if !showPortfolio {
                    allCoinsList
                        .transition(.move(edge: .leading))
                }
                if showPortfolio {
                    portfolioCoinsList
                    .transition(.move(edge: .trailing))
                }
                Spacer(minLength: 0)
            }
        }
    }
}
  • showPortfolio 변수 값에 따라 리스트 종류를 변경
  • 애니메이션 효과를 통해 변경 효과 시각적으로 보여주기

구현 화면

profile
JUST DO IT
post-custom-banner

0개의 댓글