2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Swift] TCAでSideMenuViewを実装してみた

Last updated at Posted at 2023-08-16

はじめに

こんにちは!
アプリ開発が好きで、Swiftの勉強をしている大学生です。
温かい目で見ていただけると幸いです。

やりたいこと

インターン先でTCAを使ったプロジェクトに関わっているため、TCAの勉強をしています。
そのため、以前に投稿した下記のSideMenuViewをTCAで実装してみました。

実装

まずはReducerの実装です。

public struct HogeReducer: Reducer {
    // MARK: - State
    public struct State: Equatable {
        var offset: CGFloat = 0
        var screenSizeWidth: CGFloat = 0
        var sideBarWidth: CGFloat = 0
        var showSideBar: Bool = false
    }
    
    // MARK: - Action
    public enum Action: Equatable {
        case viewAppeared(CGFloat)
        case changeShowSideBar(CGFloat)
        case sideMenuButtonTapped
        case rectangleTapped
    }
    
    // MARK: - Dependencies
    public init() {}
    
    // MARK: - Reducer
    public func reduce(into state: inout State, action: Action) -> Effect<Action> {
        switch action {
        case let .changeShowSideBar(size):
            if state.showSideBar && state.offset == 0 {
                state.offset = size - 90
            }
            
            if !state.showSideBar && state.offset == size - 90 {
                state.offset = 0
            }
            return .none
            
        case let .viewAppeared(size):
            state.screenSizeWidth = size
            state.sideBarWidth = size - 90
            return .none
            
        case .sideMenuButtonTapped:
            state.showSideBar.toggle()
            return .none
            
        case .rectangleTapped:
            state.showSideBar.toggle()
            return .none
        }
    }
}

続いてViewの実装です。

public struct HogeView: View {
    @ObservedObject private var viewStore: ViewStoreOf<HogeReducer>
    let store: StoreOf<HogeReducer>

    public init(store: StoreOf<HogeReducer>) {
        self.store = store
        self.viewStore = ViewStore(store, observe: { $0 })
    }

    public var body: some View {
        HStack(spacing: 0) {
            
            SideMenuView()
            
            VStack {
                Button("SideMenuView") {
                    viewStore.send(.sideMenuButtonTapped)
                }
            }
            .frame(width: viewStore.screenSizeWidth)
            .frame(maxHeight: .infinity)
            .overlay {
                Rectangle()
                    .fill(
                        Color.primary
                            .opacity(Double((viewStore.offset / (viewStore.screenSizeWidth - 90) ) / 5))
                    )
                    .ignoresSafeArea(.container, edges: .vertical)
                    .onTapGesture {
                        viewStore.send(.rectangleTapped)
                    }
            }
        }
        .frame(width: viewStore.screenSizeWidth + viewStore.sideBarWidth)
        .offset(x: -viewStore.sideBarWidth / 2)
        .offset(x: viewStore.offset > 0 ? viewStore.offset : 0)
        .onChange(of: viewStore.showSideBar) { _ in
            viewStore.send(.changeShowSideBar(getScreenRect()), animation: .default)
        }
        .onAppear {
            viewStore.send(.viewAppeared(getScreenRect()))
        }
    }
}

これで実装できました!
TCA慣れるまでかなり時間かかりそうです...

終わりに

誰かの役に立つことができていれば幸いです。
アウトプットを頑張ろうと思っているので温かい目で見ていただけると嬉しいです。

2
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?