2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RxSwiftのシンプルな説明

Last updated at Posted at 2018-08-09

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を利用する。

ViewController.swift
import UIKit
import RxSwift

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

ViewController.swift
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)
}

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

ViewController.swift
class RxSwiftSample {

}

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

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

ViewController.swift
class RxSwiftSample {
    private let subject = PublishSubject<Int>()

    var event : Observable<Int>{
        return subject
    }
    
    func myFunc(){
        // 処理
        print("myFuncが呼ばれました。")
        // イベント発行
        subject.onNext(self.data)
    }
}

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

ViewController.swift
private let model = RxSwiftSample()
private let disposeBag = DisposeBag()

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

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

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

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

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

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

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

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

最後に

ちなみに、RxSwiftの何が嬉しいのかということだが、例えば、カウントが10以上になったら、ラベルとかボタンの色を赤に変えるとかが、一箇所に簡単に書けます。

ViewController.swift
        //Reactive処理
        model.event.subscribe(
                onNext: {value in
                    countLbl.text = String(value)
                    //
                    if(value > 10) {
                        countLbl.backgroundColor = UIColor.red
                    }
                })
                .disposed(by: disposeBag)

なかなかメリットが多そうです。

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

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

ViewController.swift
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)
    }
}

Lovly Swift!!!

2
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?