0
0

More than 1 year has passed since last update.

はじめに

TCAでモーダル遷移時にSubViewに値を渡す方法を記録しておきます。
間違っている箇所やもっと良い方法がある箇所があるかもしれません。
もしあればコメントで教えていただけると助かります。

やりたいこと

Simulator Screen Recording - iPhone 14 Pro - 2023-09-16 at 20.55.40.gif

実装

ContentViewからSubViewに遷移させます。

ContentView

ContentView.swift
import SwiftUI

struct ContentView: View {
    @ObservedObject private var viewStore: ViewStoreOf<ContentReducer>
    
    let store: StoreOf<ContentReducer>
    
    init(store: StoreOf<ContentReducer>) {
        self.store = store
        self.viewStore = ViewStore(store, observe: { $0 })
    }
    
    var body: some View {
        VStack(spacing: 30) {
            Text(viewStore.count.description)
            
            Button {
                viewStore.send(.plusButtonTapped)
            } label: {
                Text("+")
            }

            Button {
                viewStore.send(.minusButtonTapped)
            } label: {
                Text("-")
            }
            
            Button {
                viewStore.send(.onPresentButtonTapped)
            } label: {
                Text("表示")
            }
        }
        .sheet(store: store.scope(state: \.$subState, action: ContentReducer.Action.subAction)) { store in
            SubView(store: store)
        }
    }
}
ContentReducer.swift
import Foundation
import ComposableArchitecture

public struct ContentReducer: Reducer {
    public init() {}

    // MARK: - State
    public struct State: Equatable {
        @PresentationState var subState: SubReducer.State?
        var count = 0
        
        public init() {}
    }

    // MARK: - Action
    public enum Action: Equatable {
        case subAction(PresentationAction<SubReducer.Action>)
        case onPresentButtonTapped
        case plusButtonTapped
        case minusButtonTapped
    }

    // MARK: - Reducer
    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .onPresentButtonTapped:
                state.subState = .init(count: state.count) // ここで代入されることによってモーダルが表示される
                return .none
            case .subAction:
                return .none
            case .plusButtonTapped:
                state.count += 1
                return .none
            case .minusButtonTapped:
                state.count -= 1
                return .none
            }
        }
        .ifLet(\.$subState, action: /Action.subAction) {
            SubReducer() // ここがないと`dismiss`できなくなる
        }
    }
}

SubView

SubView.swift
import SwiftUI

struct SubView: View {
    @ObservedObject private var viewStore: ViewStoreOf<SubReducer>
    
    let store: StoreOf<SubReducer>
    
    init(store: StoreOf<SubReducer>) {
        self.store = store
        self.viewStore = ViewStore(store, observe: { $0 })
    }
    
    var body: some View {
        VStack(spacing: 30) {
            Text(viewStore.count.description)
            
            Button {
                viewStore.send(.onDismissButtonTapped)
            } label: {
                Text("閉じる")
            }
        }
    }
}
SubReducer.swift
import Foundation
import ComposableArchitecture

public struct SubReducer: Reducer {
    @Dependency(\.dismiss) var dismiss // モーダルを閉じるために必要

    public init() {}

    // MARK: - State
    public struct State: Equatable {
        var count: Int // ここで欲しい値を受け取る
        
        public init(count: Int) {
            self.count = count
        }
    }

    // MARK: - Action
    public enum Action: Equatable {
        case onDismissButtonTapped
    }

    // MARK: - Reducer
    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .onDismissButtonTapped:
                return .run { _ in await self.dismiss() } // ここで閉じる
            }
        }
    }
}

おわり

TCAはむずいです

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0