RxSwiftのシンプルな説明

RxSwiftのシンプルな説明

Swiftで簡単なアプリを写経するのは簡単なのであるが、やはり実用的なアプリを作成するには、レスポンシブでないと役な立たない(お客さん受けしない)よねということで、RxSwiftを学んでみた。

正直、3日間くらい、泣きながら、挫けそうになりながら、禿げそうになりながら食らいついていた。

はっきりいって理解するのがキツイ。

■ 開発環境
OS : MacOS High Sierra Version 10.13.6
Xcode : Version 9.4.1

■ サンプリアプリ
ボタンを押すとカウントアップするだけのアプリ。

スクリーンショット 2018-08-09 14.11.12.png

■ ソースコード解説
ViewController.swiftのコードを説明する。

まずは、必要なライブラリをimportする。ここでは、RxSwiftを利用する。

[objc]
import UIKit
import RxSwift
[/objc]

先に、ラベルとボタンを配置する。
StreatBoardでも良いのであるが、敢えてコードで記述。

[objc]
class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Label
let countLbl = UILabel()
countLbl.text = "0"
countLbl.textAlignment = .center
countLbl.textColor = UIColor.blue
countLbl.frame = CGRect(x: (self.view.frame.width-110)/2, y: 150, width: 110, height: 21)

// Button
let countUpBtn = UIButton()
countUpBtn.frame = CGRect(x: (self.view.frame.width-100)/2, y: 200, width: 100, height: 30)
countUpBtn.layer.borderWidth = 1.0
countUpBtn.layer.borderColor = UIColor.blue.cgColor
countUpBtn.layer.cornerRadius = 5.0
countUpBtn.setTitleColor(UIColor.blue, for: .normal)
countUpBtn.setTitle("カウントUP", for: .normal)
countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside)

self.view.addSubview(countLbl)
self.view.addSubview(countUpBtn)
}
[/objc]

次に、RxSwiftの肝であるクラスを作成する。

[objc]
class RxSwiftSample {

}
[/objc]

RxSwiftSampleクラスには、private宣言されたsubjectPublishSubject<Int>()でインスタンス化して保持しておく。それと、そのsubjectをObservableとして返すeventを定義する。
そして、実際の処理を外部から呼べる myFunc()メソッドを定義する。その中で、onNextとかいうイベントを発行する。

これが基本的な雛形という感じかな?

[objc]
class RxSwiftSample {
private let subject = PublishSubject<Int>()

var event : Observable<Int>{
return subject
}

func myFunc(){
// 処理
print("myFuncが呼ばれました。")
// イベント発行
subject.onNext(self.data)
}
}
[/objc]

次に、このRxSwiftSampleクラスの使い方なのであるが、ViewControllerから利用できるように、RxSwiftSampleをモデルとしてmodelで宣言しておく。また、後で利用するdisposeBagも宣言しておく。

[objc]
private let model = RxSwiftSample()
private let disposeBag = DisposeBag()
[/objc]

上記を、ViewControllerから利用する。
先ずは、順を追ってわかりやすく、ボタンに対して、countUp(_ sender: UIButton)が呼ばれるように記述する。これは特に問題はないはず。
重要なのは、ここからmodelmyFunc()を呼び出すことである。

[objc]
override func viewDidLoad() {
//ボタンへイベント登録
countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside)
}

@objc func countUp(_ sender: UIButton){
print("カウントアップ")
//Modelの関数呼び出し
model.myFunc()
}

[/objc]

ここから、理解が進むと思うが、model.myFunc()で処理を行うと、事前に登録されているsubscribeで通知される。そして、 subject.onNext(self.data)で渡されたパラメータも、value で受け取れる。

[objc]
//Reactive処理
model.event.subscribe(
onNext: {value in
print("ここで通知")
countLbl.text = String(value)
})
.disposed(by: disposeBag)

[/objc]

これで、ようやく頭の中で処理シーケンスがつながった。
それでも理解できない場合は、私と同じように1日悩んで、print()仕掛けて、処理を追ってみると良いと思う。

やはり、このようなフレームワークやデザインパターンの理解は正直キツイ。それでも、時間を掛けて手を動かすのが、ベストプラクティスだと思う。

その助けになればと祈る。情報がちょっと時代遅れ感はあるのだが・・・。
始めたのが遅いので仕方ない。w

■ 最後に

ここに記したコードは、自分がRxSwiftの構造を理解するために作成したコードです。間違い等がございましたらご指摘願います。

下記、全ソースコードです。

[objc]
import UIKit
import RxSwift

private let model = RxSwiftSample()
private let disposeBag = DisposeBag()

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Label
let countLbl = UILabel()
countLbl.text = "0"
countLbl.textAlignment = .center
countLbl.textColor = UIColor.blue
countLbl.frame = CGRect(x: (self.view.frame.width-110)/2, y: 150, width: 110, height: 21)

// Button
let countUpBtn = UIButton()
countUpBtn.frame = CGRect(x: (self.view.frame.width-100)/2, y: 200, width: 100, height: 30)
countUpBtn.layer.borderWidth = 1.0
countUpBtn.layer.borderColor = UIColor.blue.cgColor
countUpBtn.layer.cornerRadius = 5.0
countUpBtn.setTitleColor(UIColor.blue, for: .normal)
countUpBtn.setTitle("カウントUP", for: .normal)
countUpBtn.addTarget(self, action: #selector(ViewController.countUp(_:)), for: UIControlEvents.touchUpInside)

self.view.addSubview(countLbl)
self.view.addSubview(countUpBtn)

//Reactive処理
model.event.subscribe(
onNext: {value in
countLbl.text = String(value)
})
.disposed(by: disposeBag)
}

@objc func countUp(_ sender: UIButton){
//Modelの関数呼び出し
model.myFunc()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}

}

class RxSwiftSample {
private let subject = PublishSubject<Int>()
private var data = 0

var event : Observable<Int>{
return subject
}

func myFunc(){
// 処理
data = data + 1

// イベント発行
subject.onNext(self.data)
}
}
[/objc]

Lovly Swift!!!

This entry was posted in iOS, Swift, Xcode, 技術情報. Bookmark the permalink.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です