あたも技術ブログ

セットジャパンコーポレーションの社員が運営しています。

【RxSwift】RxSwiftを触ってみる

RxSwiftとは

ReactiveX(Reactive Extensions)のSwift実装で非同期のイベントベースのプログラムを実装するためのライブラリです。

導入

CocoaPodsやCarthageで導入可能です。

今回はCocoaPodsを使います。

target 'RxSwiftTest' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!
  pod 'RxSwift',    '~> 3.0'
  pod 'RxCocoa',    '~> 3.0'
  # Pods for RxSwiftTest

  target 'RxSwiftTestTests' do
    inherit! :search_paths
    # Pods for testing
    pod 'RxBlocking', '~> 3.0'
    pod 'RxTest',     '~> 3.0'
  end

  target 'RxSwiftTestUITests' do
    inherit! :search_paths
    # Pods for testing
    pod 'RxBlocking', '~> 3.0'
    pod 'RxTest',     '~> 3.0'
  end

end

使ってみる

テキストフィールドの入力をラベルへリアルタイムに反映してみます。

RxSwiftを使わないで実装する場合はUITextFieldのDelegateを実装したりNotificationを使う必要があります。

f:id:atamo_dev:20170515200329g:plain:w300

Delegateでの実装

class ViewController: UIViewController, UITextFieldDelegate {
    
    var label: UILabel = UILabel()
    var field: UITextField = UITextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ラベルをViewへ追加
        label.frame.size = CGSize(width: UIScreen.main.bounds.size.width, height: 60)
        label.center = CGPoint(x: view.center.x, y: view.center.y - 100)
        view.addSubview(label)
        
        // テキストフィールドをViewへ追加
        field.frame.size = CGSize(width: UIScreen.main.bounds.size.width, height: 60)
        field.center = view.center
        field.borderStyle = .roundedRect
        field.delegate = self
        view.addSubview(field)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
    }
    
    // MARK: - UITextFieldDelegate
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text as NSString? else {
            return false
        }
        label.text = text.replacingCharacters(in: range, with: string)
        return true
    }
}

RxSwiftでの実装

これをRxSwiftで実装するとこうなります。

import UIKit
import RxSwift      
import RxCocoa      

let disposeBag = DisposeBag()   

class ViewController: UIViewController {
    
    var label: UILabel = UILabel()
    var field: UITextField = UITextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ラベルをViewへ追加
        label.frame.size = CGSize(width: UIScreen.main.bounds.size.width, height: 60)
        label.center = CGPoint(x: view.center.x, y: view.center.y - 100)
        view.addSubview(label)
        
        // テキストフィールドをViewへ追加
        field.frame.size = CGSize(width: UIScreen.main.bounds.size.width, height: 60)
        field.center = view.center
        field.borderStyle = .roundedRect
        view.addSubview(field)
        
        // テキストフィールドのテキストをラベルへバインド
        field.rx.text.map {$0}.bindTo(label.rx.text).addDisposableTo(disposeBag)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
    }
    
}

DelegateやNotificationを使用した場合は処理がいろいろな場所へ散乱してしまい非常に読みづらいですが、RxSwiftを使うとスッキリと書くことができます。

参考

http:// http://qiita.com/jollyjoester/items/c4013c60acd453ea7248