Last active
December 7, 2018 17:49
-
-
Save yamazaki-sensei/abb2d3485ec80a1bd58df2e54d62c768 to your computer and use it in GitHub Desktop.
ReSwiftを使うときに可能な限り再描画を避けたい話 ref: https://qiita.com/yamazaki_sensei/items/90a7c31f8f930a6c9986
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import UIKit | |
| protocol AvoidRerender: class { | |
| associatedtype TargetState: Equatable | |
| // この記事を書いている途中で、これがinternalなのはまずいことに気付いた。が、現状どうしようもない。 | |
| var state: TargetState? { get set } | |
| func update(with state: TargetState?) | |
| func customAction(state: TargetState?) | |
| } | |
| extension AvoidRerender where Self: UIViewController { | |
| func update(with state: TargetState?) { | |
| guard state != self.state else { return } | |
| self.state = state | |
| customAction(state: state) | |
| self.view.setNeedsLayout() | |
| } | |
| } | |
| extension AvoidRerender where Self: UIView { | |
| func update(with state: TargetState?) { | |
| guard state != self.state else { return } | |
| self.state = state | |
| customAction(state: state) | |
| setNeedsLayout() | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import ReSwift | |
| struct CounterState: StateType { | |
| var count = 0 | |
| } | |
| extension CounterState: Equatable { | |
| static func == (lhs: CounterState, rhs: CounterState) -> Bool { | |
| return lhs.count == rhs.count | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class View: UIView { | |
| let viewModel = ViewModel() | |
| init() { | |
| super.init() | |
| viewModel.cacheObservable.subscribe(onNext: {[weak self] value in | |
| self.update(with: value) | |
| }).disposed(by: disposeBag) | |
| } | |
| private func update(with value: Int) { | |
| // 何かする | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class View: UIView { | |
| private var cache: Int? // 外部には絶対見せない | |
| // storeにsubscribeしているViewControllerから呼んでもらうメソッド | |
| func updateWithState(state: State) { | |
| guard state.value != cache else { return } | |
| update(with: state.value) | |
| } | |
| private func update(with value: Int) { | |
| // 何かする | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extension ViewController: StoreSubscriber, AvoidRerender { | |
| typealias TargetState = CounterState | |
| typealias StoreSubscriberStateType = CounterState | |
| // protocol extension内で StoreSubscriber を実装して、 newState もデフォルト実装してしまっていいかも | |
| func newState(state: CounterState) { | |
| update(with: state) | |
| } | |
| func customAction(state: CounterState?) { | |
| print("customAction called") | |
| guard let state = state else { | |
| valueLabel.text = "" | |
| return | |
| } | |
| valueLabel.text = "\(state.count)" | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Intの状態変化をViewに伝えたい場合 | |
| // 擬似コード。実際には動かない。 | |
| import RxSwift | |
| class ViewModel { | |
| private let cache = BehaviorRelay<Int>(value: 0) | |
| var cacheObservable: Observable<Int> { | |
| return cache.asObservable() // 外部から値を設定できないように、Observableだけ公開しておく | |
| } | |
| // storeにsubscribeしているViewControllerから呼んでもらうメソッド | |
| func updateWithState(state: State) { | |
| guard state.value != cache.value else { return } // これで再描画を避けられるはず | |
| cache.accept(state.value) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment