【iOS】RxSwiftを使ってMVVMなカウントダウンタイマーの作り方
リアクティブなカウントダウンタイマーの作り方
手書きでQiita書いたので誤字脱字あったらお許しください...
ViewController
ViewController.swift
class ViewController: UIViewController {
@IBOutlet private weak var countLabel: UILabel!
@IBOutlet private weak var startButton: UIButton!
@IBOutlet private weak var stopButton: UIButton!
private var viewModel: ViewModel!
private let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
setupViewModel()
}
private func setupViewModel() {
let input = ViewModel.Input(
startButtonTapped: startButton.rx.tap.asObservable(),
stopButtonTapped: stopButton.rx.tap.asObservable()
)
viewModel = ViewModel(trigger: input)
// output
viewModel.output().count
.map { "あと:\($0)秒" }
.bind(to: countLabel.rx.text)
.disposed(by: disposeBag)
}
}
ViewModel
ViewModel.swift
class ViewModel {
struct Input {
var startButtonTapped: Observable<Void>
var stopButtonTapped: Observable<Void>
}
struct Output {
var count: Observable<Int>
}
private var input: ViewModel.Input!
private var output: ViewModel.Output!
private let isValidTimerRelay = BehaviorRelay<Bool>(value: false)
private let countRelay = BehaviorRelay<Int>(value: 60) // 初期値: 60秒 (任意)
private let disposeBag = DisposeBag()
init(trigger: ViewModel.Input) {
input = trigger
output = ViewModel.Output(
count: countRelay.asObservable()
)
bind()
setupTimer()
}
// MARK: Actions
private func bind() {
// start button tapped
input.startButtonTapped
.map { true }
.bind(to: isValidTimerRelay)
.disposed(by: disposeBag)
// stop button tapped
input.stopButtonTapped
.map { false }
.bind(to: isValidTimerRelay)
.disposed(by: disposeBag)
}
// MARK: Timer
private func setupTimer() {
let period = DispatchTimeInterval.seconds(1) // 1秒間隔で実行
isValidTimerRelay
.flatMapLatest {
$0 ? Observable<Int>.interval(period, scheduler: MainScheduler.instance) : Observable.empty()
}
.map { [weak self] _ in
guard let value = self?.countRelay.value else { return nil }
return value - 1
}
.filter { [weak self] _ in
guard let value = self?.timerValueRelay.value else { return false }
return value >= 0 ? true : false
}
.unwrap()
.bind(to: countRelay)
.disposed(by: disposeBag)
}
// MARK: -- OUTPUT
func output() -> ViewModel.Output {
output
}
}
こんな感じで動くかと!! ぜひ試してみてください😁
参考
RxSwift | GitHub
[iOS] RxSwiftのIntervalオペレータを使用して一定間隔で処理を行う
【iOS】MVVMについて
Author And Source
この問題について(【iOS】RxSwiftを使ってMVVMなカウントダウンタイマーの作り方), 我々は、より多くの情報をここで見つけました https://qiita.com/shin1007m/items/3e38228ccb672fadd001著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .