Kinokのブログ

しゃかいじん。

ReSwift触ってみた

概要

Swiftでreduxを実現するならReSwiftというパッケージが良いらしいです。

サンプルをクローン

下記が公式のカウンターアプリです。 コードを見てみます。 github.com

ディレクトリ構成

下記のような構成です。

- Reducers
- Actions
- State
AppDelegate
ViewController

State

状態の構造体を定義する場所

import ReSwift

struct AppState: StateType {
    var counter: Int = 0
}

Actions

Actionを定義する場所。同一ファイルに全部まとめる

import ReSwift

// all of the actions that can be applied to the state
struct CounterActionIncrease: Action {}
struct CounterActionDecrease: Action {}

Reducers

reducerを定義する場所。(ReducerとはActionとStateを受け取って、処理をまとめる場所)

import ReSwift

// the reducer is responsible for evolving the application state based
// on the actions it receives
func counterReducer(action: Action, state: AppState?) -> AppState {
    // if no state has been provided, create the default state
    var state = state ?? AppState()
    
    switch action {
    case _ as CounterActionIncrease:
        state.counter += 1
    case _ as CounterActionDecrease:
        state.counter -= 1
    default:
        break
    }
    
    return state
}

AppDelegate

AppDelegateがまだキャッチアップできていないものの、起動時の時だけmainStoreをインスタンス化してGlobalに扱ってるっぽい。。?

import UIKit
import ReSwift

// The global application store, which is responsible for managing the appliction state.
let mainStore = Store<AppState>(
    reducer: counterReducer,
    state: nil
)

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        return true
    }

}

ViewController

ViewとStoreを紐づけたり、UIアクションと処理を紐づけたりしているっぽい

import UIKit
import ReSwift


class ViewController: UIViewController, StoreSubscriber {
    typealias StoreSubscriberStateType = AppState

    
    @IBOutlet weak var counterLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // subscribe to state changes
        mainStore.subscribe(self)
    }
    
    func newState(state: AppState) {
        // when the state changes, the UI is updated to reflect the current state
        counterLabel.text = "\(mainStore.state.counter)"
    }
    
    // when either button is tapped, an action is dispatched to the store
    // in order to update the application state
    @IBAction func downTouch(_ sender: AnyObject) {
        mainStore.dispatch(CounterActionDecrease());
    }
    @IBAction func upTouch(_ sender: AnyObject) {
        mainStore.dispatch(CounterActionIncrease());
    }

}

まとめ

SwiftUIと組み合わせて使えるものだと期待していたけれど、そういうわけではなさそう。。 Storyboardぽちぽちはあまり得意ではないのでなんとかSwiftUIに慣れていきたい。