SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Swift 4で最初に知っておきたい3つのポイント

Swift 4における、プロパティを利用した処理とUIの制御

Swift 4で最初に知っておきたい3つのポイント 第4回

プロパティを利用して処理を簡易的に記述する【Swift 4】

 Swiftでは、プロパティの値が変化した際に呼び出されるwillSet/didSetという関数があります。これらの関数はプロパティを監視する目的で定義されていますが、うまく使うことでプロパティの値の変化をUIに反映することも可能です。ここからは、プロパティの値の変化とUIへの反映について具体的なサンプルを挙げながら説明します。

プロパティの値が変化した際に処理を行う

 プロパティの値が変化した際に処理を行うwillSet/didSet関数について、両者の違いは次の通りです。

willSet/didSet関数の概要
関数名 呼ばれるタイミング 得られる値
willSet 値が変更される直前 変更後の値
didSet 値が変更された後 変更前の値

 呼び出されるタイミングと得られる値が両者で逆になっていることに気をつけてください。willSet/didSet関数を利用する際には、プロパティを定義する際に次の書式で関数を記述します。

リスト4 willset/didset関数の書式
var プロパティ名 [:型] = 初期値 {
    willSet[(newValue)]{
         // 処理
    }
    didSet[(oldValue)]{
         // 処理
    }
}

 willSet/didSetメソッドの引数は使わない場合に省略可能で、関数自体も利用しない場合は記述しなくて構いません。また、関数の処理に関しては仕様上は処理内容に規制はありません。

 didSet関数を利用する簡単な例を次に挙げます。

リスト5 PropertyViewController.swift
class PropertyViewController: UIViewController {
    
    var num: Int = 0 {
        didSet(oldValue){
            if num > oldValue { return }  // 元の値より大きければ何もしない
            
            print("元の値より大きい値を入力してください。")
            num = oldValue  // 前の値のまま
        }
    }
    
    override func viewDidLoad() {
        num = 3
        print("代入後: \(num)")   //  結果:代入後: 3
        num = 2
        print("代入後: \(num)")  //  結果:元の値より大きい値を入力してください。代入後: 3
        num = 4
        print("代入後: \(num)")  //  結果:代入後: 4
    }
}

 リスト5の例では、Int型のプロパティnumの値を代入した後に、代入前の値と比べて大きい値でなければ代入できないようにしています。didsetメソッドを利用すると、こうした値を参照しての制限を容易にかけることが可能です。サンプルの通り、ビューコントローラー内に特別な処理を記述することなく、プロパティの値に関しての処理を行うことができます。

UIの入力制限を行う

 didSet関数を利用し、会員登録の画面などでよく利用される入力内容によってボタンの有効化を行うサンプルを作成してみます。

作成するサンプル
作成するサンプル

 2つの入力欄に入力がある場合のみ、ナビゲーションバーの保存ボタンが押せるようになるサンプルです。ゲームやSNSのアプリでの会員登録時によく見かける機能ですが、didSet関数を利用するとこうした入力制限も比較的容易に作成できます。

リスト6 InputViewController.swift
class InputViewController: UIViewController {

    @IBOutlet weak var saveButton: UIBarButtonItem!    // ------(1)
    @IBOutlet weak var addressTextField: UITextField!
    @IBOutlet weak var nameTextField: UITextField!
    
    var isValidated = false {    // ------(2)
        didSet {
            self.saveButton.isEnabled = self.isValidated
        }
    }

 最初にプログラム内で利用するUIをIBOutletで接続しておきます(1)。その後、保存ボタンの有効化を制御するプロパティをBool型の変数isValidatedで定義します。有効化を管理する変数を独立させておくことで処理をわかりやすくできます。プロパティを定義する定義の際に、didSetメソッドのブロック内で保存ボタンを押せる/押せないをisValidated変数の値で変更できるようにします。

リスト7 InputViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    
    // Do any additional setup after loading the view.
    self.isValidated = false    // ------(3)
}

@IBAction func textChanged(_ sender: Any) {    // ------(4)
    // 入力内容のある入力欄のみを取得
    let array = [self.nameTextField.text, self.addressTextField.text].filter{ ($0?.count ?? 0) > 0 }
    // 入力内容のある入力欄が2つならば true
    self.isValidated = array.count == 2 ? true : false
}

 画面が表示された際には、保存ボタンは無効化しておきます(3)。

 次に、画面上に配置した2つのテキストフィールドの入力内容が変更された際に発生するUIControlEvents.editingChangedオブジェクトと入力チェックの処理をIBActionで結合させます(4)。これによって入力欄2つのうち、どちらの入力内容が変更された場合にも(4)の入力チェックのメソッドが呼び出されます。

 入力内容のチェックは、配列の条件に合う要素のみを取得するfilter(_:)メソッドを利用して作成しています。入力欄の入力内容を参照するtextプロパティを参照して、2つの入力欄の入力内容を配列にします。その配列でfilter(_:)メソッドを実行し、入力内容の文字数が0より大きいもののみを取得します。その結果が2つであれば2つの入力欄に内容があるものと判断しています。

 判断した結果は、最初に定義した保存ボタンの有効化を制御するisValidated変数に代入します。isValidated変数の値が変更された際には、didSet関数が呼ばれ、保存ボタンの有効/無効を切り替えます。

 サンプルの実行結果は次の通りです。

サンプルの実行結果
サンプルの実行結果

 2つの入力欄の内容をチェックする処理にも関わらず、delegateや別々のメソッドを利用することなく、1つのプロパティと1つのメソッドで処理を完結することができます。

プロパティをオーバーライドして処理を行う

 UI部品を管理するクラスで、IBInspectableでプロパティを宣言すると、そのプロパティはストーリーボードから制御することができます。UIButtonクラスを継承して次のようにUIColor型のプロパティを宣言すると、ストーリーボードでは次のようにプロパティの内容を参照/指定できるようになります。

リスト8 ColorButton.swift
import UIKit

class ColorButton: UIButton {

    @IBInspectable var hightlightedBackgroundColor :UIColor?
    @IBInspectable var hightlightedselectedBackgroundColor :UIColor?
    @IBInspectable var selectedBackgroundColor :UIColor?
...略...
IBInspectableで宣言したプロパティ
IBInspectableで宣言したプロパティ

 UIButtonクラスのハイライト状態を制御するisHighlightedプロパティは、UIButtonクラスを継承したクラスではオーバーライドすることが可能です。これを利用して、ハイライト時や選択時の処理をdidSet関数で行うことも可能です。

リスト9 ColorButton.swift
import UIKit

class ColorButton: UIButton {

    @IBInspectable var hightlightedBackgroundColor :UIColor?
    @IBInspectable var hightlightedselectedBackgroundColor :UIColor?
    @IBInspectable var selectedBackgroundColor :UIColor?
    
    // isHighlightedをオーバーライドしてハイライト状態が変わった際の処理を行う
    override var isHighlighted: Bool {
        didSet {
            // 状態によってボタンの背景色を変える
            switch (isHighlighted, isSelected) {
            case (true, false):
                self.backgroundColor = hightlightedBackgroundColor
            case (true, true):
                self.backgroundColor = hightlightedselectedBackgroundColor
            case (false, true):
                self.backgroundColor = selectedBackgroundColor
            default:
                backgroundColor = .white
            }
        }
    }
}

 ハイライト状態はisHighlightedプロパティ、選択状態はisSelectedプロパティで参照できます。サンプルの実行結果は次の通りです。

サンプルの実行結果
サンプルの実行結果

 この図のように、UIButtonクラスが本来持っているプロパティの値が変化した際の処理もオーバーライドできます。またdidSetの中では、通常のSwiftでの処理をそのまま行えるため、サンプルの通り他のプロパティも参照し、状態に応じた処理を行うことも可能です。UI部品の状態がいくつかに分かれた場合の処理も、didSet関数を利用すると比較的容易に行うことができます。

まとめ

 アプリの画面を操作した際の処理について、今回はプロパティからUIを制御する方法について説明しました。プロパティの値が変化した際の処理に関しては、デリゲートやNotificationを利用しなくても実行できるため、ぜひ使ってみてください。

 次回はライブラリを利用して、アプリの機能を拡充する基本的な方法について説明します。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Swift 4で最初に知っておきたい3つのポイント連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 片渕 彼富(カタフチ カノトミ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10643 2018/02/19 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー