ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SwiftUI] ์ƒํƒœ๊ด€๋ฆฌ(redux)
    iOS/TCA 2023. 7. 6. 17:30

     

     

     

     

     

    PointFree ๊ฐ•์˜ Composable Architecture
    Composable State Management: Reducers ์ •๋ฆฌ

     

     

     

    ๐Ÿ“š ์ด๋ฒˆ ๊ฐ•์˜ ๋ชฉํ‘œ

     

    ์ €๋ฒˆ ๊ฒŒ์‹œ๊ธ€์—์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์—์„œ 

     

    1. Combine์œผ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ
    2. ๊ฐ’ ํƒ€์ž…์˜ ์ด์  ํ™œ์šฉ

     

    ์„ ์œ„ํ•ด ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ ์ž ํ•œ๋‹ค!

     

     

     

     

     

    ๐Ÿ“š ์ฝ”๋“œ

     

    struct AppState {
        var count = 0
        var favoritePrimes: [Int] = []
        var loggedInUser: User?
        var activityFeed: [Activity] = []
        
        var didChange = PassthroughSubject<Void, Never>()
        
        struct Activity {
            let timestamp: Date
            let type: ActivityType
            
            enum ActivityType {
                case addedFavoritePrime(Int)
                case removedFavoritePrime(Int)
            }
        }
        
        struct User {
            let id: Int
            let name: String
            let bio: String
        }
    }

     

    ๊ธฐ์กด class ํƒ€์ž…์˜ AppState ์ฝ”๋“œ๋ฅผ ๊ตฌ์กฐ์ฒด๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค. ์ด๋Ÿฌ๋ฉด ๋”์ด์ƒ @Published๋กœ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    ์—ฌ๊ธฐ์— ObservableObject๋ฅผ ์ค€์ˆ˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ตฌ์กฐ์ฒด๋ฅผ ๊ฐ์‹ธ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒˆ๋กœ ์„ ์–ธํ•ด์•ผํ•จ(Store)

     

     

     

     

     

     

     

     

    final class Store<Value, Action>: ObservableObject {
        let reducer: (inout Value, Action) -> Void
        @Published var value: Value
        
        init(initialValue: Value, reducer: @escaping (inout Value, Action) -> Void) {
          self.value = initialValue
          self.reducer = reducer
        }
        
        func send(_ action: Action) {
            self.reducer(&self.value, action)
        }
    }

     

    AppState์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋Š” Store<AppState> ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค.

     

    Store ํด๋ž˜์Šค์˜ ์—ญํ• : ๊ฐ’ ์œ ํ˜•์„ ๋ž˜ํ•‘ํ•ด์„œ ๊ด€์ฐฐ์ž์—๊ฒŒ ํ›… ์ œ๊ณต
    AppState์— ๋Œ€ํ•ด์„œ๋Š” ์•Œ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋–„๋ฌธ์— ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ์„ ์–ธ

     

     

     

     

     

     

     

    // ์‚ฌ์šฉ์ž ์•ก์…˜ ํƒ€์ž… ์ง€์ •
    enum CounterAction {
        case decrementTapped
        case incrementTapped
    }
    enum PrimeModalAction {
        case saveFavoritePrimeTapped
        case removeFavoritePrimeTapped
    }
    enum FavoritePrimesAction {
        case deleteFavoritePrimes(IndexSet)
    }
    enum AppAction {
        case counter(CounterAction)
        case primeModal(PrimeModalAction)
        case favoritePrimes(FavoritePrimesAction)
    }
    
    
    func appReducer(state: inout AppState, action: AppAction) -> Void {
        switch action {
        case .counter(.decrementTapped):
            state.count -= 1
        case .counter(.incrementTapped):
            state.count += 1
        case .primeModal(.saveFavoritePrimeTapped):
            state.favoritePrimes.append(state.count)
            state.activityFeed.append(.init(timestamp: Date(), type: .addedFavoritePrime(state.count)))
        case .primeModal(.removeFavoritePrimeTapped):
            state.favoritePrimes.removeAll(where: { $0 == state.count })
            state.activityFeed.append(.init(timestamp: Date(), type: .removedFavoritePrime(state.count)))
        case let .favoritePrimes(.deleteFavoritePrimes(indexSet)):
            for index in indexSet {
              let prime = state.favoritePrimes[index]
              state.favoritePrimes.remove(at: index)
              state.activityFeed.append(.init(timestamp: Date(), type: .removedFavoritePrime(prime)))
            }
        }
    }

     

    ์‚ฌ์šฉ์ž ์•ก์…˜ ํƒ€์ž…๊ณผ ๊ทธ์— ๋”ฐ๋ฅธ ์•ก์…˜์„ ์ •์˜ํ•œ๋‹ค

     

     

     

     

     

     

     

     

    @ObservedObject var store: Store<AppState, AppAction>

     

    ObservedObject ๋ณ€์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด์ค€๋‹ค

     

     

     

     

     

     

     

     

     

     

    ์ƒํƒœ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ํ–‰๋™์„ reducer์— ๊ฒฉ๋ฆฌํ•ด์„œ store์—์„œ send() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํ†ตํ•ด ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

     

     

     

     

     

     

     

     

Designed by Tistory.