Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on May 18, 2021. It is now read-only.

This is what makes the Flux design pattern possible.

License

NotificationsYou must be signed in to change notification settings

marty-suzuki/FluxCapacitor

Repository files navigation

Logo

FluxCapacitor

Build StatusBuild StatusVersionLicensePlatformCarthage compatible

FluxCapacitor makes implementingFlux design pattern easily with protocols and typealias.

  • Storable protocol
  • Actionable protocol
  • DispatchState protocol

Requirements

  • Xcode 10.1 or later
  • Swift 4.2 or later
  • iOS 10.0 or later

Installation

CocoaPods

FluxCapacitor is available throughCocoaPods. To installit, simply add the following line to your Podfile:

pod"FluxCapacitor"

Carthage

If you’re usingCarthage, simply add FluxCapacitor to yourCartfile:

github"marty-suzuki/FluxCapacitor"

Usage

This is ViewController sample that uses Flux design pattern. If ViewController calls fetchRepositories method of RepositoryAction, it is reloaded automatically by observed changes of Constant in RepositoryStore after fetched repositories from Github. Introducing how to implement Flux design pattern withFluxCapacitor.

finalclassUserRepositoryViewController:UIViewController{@IBOutlet weakvartableView:UITableView!privateletrepositoryAction=RepositoryAction()privateletrepositoryStore=RepositoryStore.instantiate()privateletuserStore=UserStore.instantiate()privateletdustBuster=DustBuster()privateletdataSource=UserRepositoryViewDataSource()overridefunc viewDidLoad(){        super.viewDidLoad()        dataSource.configure(with: tableView)observeStore()iflet user= userStore.selectedUser.value{            repositoryAction.fetchRepositories(withUserId: user.id, after:nil)}}privatefunc observeStore(){        repositoryStore.repositories.observe(on:.main, changes:{[weak self] _inself?.tableView.reloadData()}).cleaned(by: dustBuster)}}

Dispatcher

First of all, implementingDispatchState. It connects Action and Store, but it plays a role that don't depend directly each other.

extensionDispatcher{enumRepository:DispatchState{typealiasRelatedStoreType=RepositoryStoretypealiasRelatedActionType=RepositoryActioncase isRepositoryFetching(Bool)case addRepositories([GithubApiSession.Repository])case removeAllRepositories}}

Store

ImplementingStore withStorable protocol.func reduce(with:_) is called when Dispatcher dispatches DispatchStateType. Please update store's value with Associated Values.

finalclassRepositoryStore:Storable{typealiasDispatchStateType=Dispatcher.RepositoryletisRepositoryFetching:Constant<Bool>privatelet_isRepositoryFetching=Variable<Bool>(false)letrepositories:Constant<[Repository]>privatelet_repositories=Variable<[Repository]>([])requiredinit(){self.isRepositoryFetching=Constant(_isRepositoryFetching)self.repositories=Constant(_repositories)}func reduce(with state:Dispatcher.Repository){switch state{case.isRepositoryFetching(let value):            _isRepositoryFetching.value= valuecase.addRepositories(let value):            _repositories.value.append(contentsOf: value)case.removeAllRepositories:            _repositories.value.removeAll()}}}

If you want to use any store, please useXXXStore.instantiate(). That static method returns its reference or new instance.If you want to unregister any store from Dispatcher, please callxxxStore.clear().

Action

ImplementingAction withActionable protocol. If you call invoke method, it can dispatch value related DispatchStateType.

finalclassRepositoryAction:Actionable{typealiasDispatchStateType=Dispatcher.Repositoryprivateletsession:ApiSessioninit(session:ApiSession=.shared){self.session= session}func fetchRepositories(withUserId id:String, after:String?){invoke(.isRepositoryFetching(true))letrequest=UserNodeRequest(id: id, after: after)        _= session.send(request){[weak self]inswitch $0{case.success(let value):self?.invoke(.addRepositories(value.nodes))case.failure:break}self?.invoke(.isRepositoryFetching(false))}}}

Observe changes withConstant<Element> /Variable<Element>

You can initialize a store withinstantiate(). If reference of store is left, that method returns remained one. If reference is not left, that method returns new instance.You can observe changes by Constant or Variable. When called observe, it returnsDust. So, clean up withDustBuster.

letdustBuster=DustBuster()func observeStore(){    // Get store instanceletstore=RepositoryStore.instantiate()    // Observer changes of repositories that is `Constant<[Github.Repository]>`.    store.repositories.observe(on:.main){ valuein            // do something}.cleaned(by: dustBuster)}

dustbusterRobert Zemeckis (1989) Back to the future Part II, Universal Pictures

Constant<Element> andVariable<Element>

Variable<Element> has getter and setter of Element.

letintVal=Variable<Int>(0)intVal.value=1print(intVal.value) // 1

Constant<Element> has only getter of Element. So, you can initialize Constant with Variable.Variable shares its value with Constant.

letvariable=Variable<Int>(0)letconstant=Constant(variable)variable.value=1print(variable.value) // 1print(constant.value) // 1

In addition, Constant that initialize with some Variable, it can use same observation.

letvariable=Variable<Int>(0)letconstant=Constant(variable)_= variable.observe{ valueinprint(value) // 0 -> 10}_= constant.observe{ valueinprint(value) // 0 -> 10}variable.value=10

with RxSwift

You can use FluxCapacitor with RxSwift likethis link.

Or implementfunc asObservable() like this.

// ConstantextensionPrimitiveValuewhere Trait==ImmutableTrait{func asObservable()->Observable<Element>{returnObservable.create{[weak self] observerinletdust=self?.observe{ observer.onNext($0)}returnDisposables.create{ dust?.clean()}}}}

Example

To run the example project, clone the repo, and runpod install andcarthage update from the Example directory first. In addition, you must set Github Personal access token.

// ApiSessionType.swiftextensionApiSession:ApiSessionType{staticletshared:ApiSession={lettoken="" // Your Personal Access TokenreturnApiSession(injectToken:{InjectableToken(token: token)})}()}

Application structure is like below.

flux_image

GithubKitForSample is used in this sample project.

Additional

Flux + MVVM Sample ishere.

Migration Guide

FluxCapacitor 0.10.0 Migration Guide

Author

marty-suzuki,s1180183@gmail.com

License

FluxCapacitor is available under the MIT license. See the LICENSE file for more info.

About

This is what makes the Flux design pattern possible.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp