Swift,Objective-Cプログラミング ~ iOS ~

Objective-C,Swift,Apple Watchなどのプログラミング

【iOS Swift入門 #299】[RxSwift]バインドできるプロパティを作成する

この記事を読んでわかること

  • RxSwift(RxCocoa)でUIプロパティを拡張すること

はじめに

RxSwift(RxCocoa)ではObservableのbind(to:)メソッドを使い、 ObservableとUI部品のプロパティをバインドすることができます。

例)テキストフィールドの入力をラベルにバインドする

textField.rx.text.asObservable()
    .bindTo(label.rx.text)
    .disposed(by: bag)

RxCocoaではUILabelでバインドできるプロパティは
textとattributedTextの2つしか用意されていません。
他のプロパティもバインドできるようにしたい場合、
どうすればいいのか?

UIプロパティを拡張する

例として、テキストフィールドの入力文字数が

  • 奇数の場合、ラベルの背景色を黄色にする
  • 偶数の場合、ラベルの背景色を青にする

をバインドを使って実現したいとします。

RxCocoaではUILabelのbackgroundColorプロパティは用意されていません。
rxからアクセスできるtextプロパティやattributedTextプロパティが
どのように作成されているか、実際のソースを見てみます。

UILabel+Rx.swift

    //
    //  UILabel+Rx.swift
    //  RxCocoa
    //
    //  Created by Krunoslav Zaher on 4/1/15.
    //  Copyright © 2015 Krunoslav Zaher. All rights reserved.
    //
    
    #if os(iOS) || os(tvOS)
    
    #if !RX_NO_MODULE
    import RxSwift
    #endif
    import UIKit
    
    extension Reactive where Base: UILabel {
        
        /// Bindable sink for `text` property.
        public var text: UIBindingObserver<Base, String?> {
            return UIBindingObserver(UIElement: self.base) { label, text in
                label.text = text
            }
        }
    
        /// Bindable sink for `attributedText` property.
        public var attributedText: UIBindingObserver<Base, NSAttributedString?> {
            return UIBindingObserver(UIElement: self.base) { label, text in
                label.attributedText = text
            }
        }
        
    }
    
    #endif

UIBindingObserverタイプのプロパティを作ってあげればよいとわかります。
ここではbackgroundColorという名前でプロパティを作成します。

UILabel+Sample.swiftという名前でファイルを作成しました。

    import RxSwift
    import RxCocoa
    
    extension Reactive where Base: UILabel{
        var backgroundColor: UIBindingObserver<Base, UIColor>{
            return UIBindingObserver(UIElement: self.base){
                label, backgroundColor in
                label.backgroundColor = backgroundColor
            }
        }
    }

これを使ってテキストフィールドとラベルをバインドします。

    import UIKit
    import RxSwift
    import RxCocoa
    
    class ViewController: UIViewController {
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var label: UILabel!
        private let bag = DisposeBag()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            textField.rx.text.asObservable()
                .map(toColor(from:))
                .bindTo(label.rx.backgroundColor)
                .disposed(by: bag)
            
        }
        
        // 文字数からUIColorを計算する
        private func toColor(from text:String?) -> UIColor{
            let isEven = ((text ?? "").characters.count % 2 == 0)
            let color = isEven ? UIColor.blue : UIColor.yellow
            return color
        }
    }

サンプルアプリ

①アプリを起動します テキストフィールドの入力文字数は、0文字で偶数なので、ラベルの背景色は青となります。

f:id:fjswkun:20170428145005p:plain

②1文字入力します テキストフィールドの入力文字数は、1文字で奇数なので、ラベルの背景色は黄となります。

f:id:fjswkun:20170428145034p:plain

③もう1文字入力します。(合計2文字となります) テキストフィールドの入力文字数は、2文字で偶数なので、ラベルの背景色は青となります。

f:id:fjswkun:20170428145048p:plain

サンプルソースのダウンロード

SampleCreateBinder.zip - Google ドライブ

Swift

入門書籍

絶対に挫折しない iPhoneアプリ開発「超」入門 増補改訂第5版
プログラミングが初めて!という人が小さなアプリを作ることで、アプリ開発を学ぶことができます。
「Swiftだけでなく、プログラミング自体が初めてなんだけど、どの本が良い?」と聞かれたときには、
この書籍をおすすめしています。

本気ではじめるiPhoneアプリ作り Xcode 8.x+Swift 3.x対応 (ヤフー黒帯シリーズ)
アプリ開発からApp Storeへの公開までの一通りを学ぶことができます。
入門書を2冊、3冊を読んだあとでこの書籍を読むとかなりの実力アップを感じることができます。

ただし、一通り学ぶことができますが、プログラミング初めてでこの書籍を選ぶことはオススメできません。
最初の方の内容はプログラミング初心者には理解が難しく、そこで勉強をやめてしまう可能性がありそうだと感じます。

Swiftポケットリファレンス
辞書として1冊は持ってても良い。

仕事でやれるレベルになるために

初心者から仕事でやれるレベルになるためにオススメできる日本語書籍がみつかりませんでした。
英語は苦手でも、書籍に書かれているソースはやさしく、読み進めることができます。

The iOS Apprentice (英語サイト・英語書籍)
Swift Apprentice (英語サイト・英語書籍)

平均的プログラマーを超えるために

詳解Swift 第3版
Swift3の書籍。第1版、第2版にもお世話になっています。
Swiftの文法についてとても詳しく書いてあります。

Ray Wenderlich | Tutorials for iPhone / iOS Developers and Gamers
QiitaのSwiftに関する記事