• Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
  • 初心者はここから!-> 50オヤジでもできるiOS開発
  • 私の本業、オフィシャルなブログ-> Life-LOG
  • Swift 3 対応

チュートリアル索引に戻る→

2017年3月27日:Swift 3に向けて改訂中*1

ここまでスムーズに理解できました。やはりだてに1年勉強していたわけじゃないなと思えました(笑)。じゃあ次の課題はどうでしょう。

今日からカスタムUIViewに取り組みます。

developer.apple.com

習うべき項目は以下です。

  • storyboardのエレメントをカスタムコードで制御する。
  • カスタムクラスを定義
  • カスタムクラスに初期化ステップを組み込む
  • コンテナとしてUIViewクラスを使う
  • プラグラム的に画面を表示させるステップの理解

重要なステップですね。今まで挫折していた内容を含みます。さて今回どれだけ理解できることやら。

これまでのチュートリアルでPhotoLibraryにある食事の写真を取り込むことができるようになりました。

f:id:yataiblue:20150708065504j:plain

次にその食事にレイティングを付ける機能を実装していくのですが、白い☆が5つ並んでタップすると黒い★に変化するオブジェクトをカスタムで作ります。

画面に設置するエレメントを用意するためにUIViewクラスを使っていましたが、Swift 3からUIViewを継承した「UIStackView」の使用に替わりました。

Swiftで遊ぼう! - ref1: カスタムクラスの準備 - Swiftで遊ぼう! on Hatena

ここの手順通りにUIStackViewクラスを継承した「RatingControl」を作ります。

プロジェクト・ナビゲーションに「RatingControl.swift」ができたので選択します。コメントやテンプレートのコードが並んでいるので、すべて消去します。

import: UIKit

class RatingControl: UIStackView {

}

UIStackViewをマニュアル的に実装するために必要なのは初期化ステップです。

init()を使ったイニシャライザが必要になります。

  • frameを組み込んで手動でUIStackViewを初期化
  • ストーリーボードを使って初期化

UIStackViewの初期化ステップはUIViewの初期化ステップと同様です。スタンフォード大学のポール先生の説明では、できるだけ初期化を避けてUIViewを実体化するのが望ましいと仰っています。なぜ? 彼はデモの中でinit()を使っていません。

yataiblue.hatenablog.com

ちゃんと理解できていなかったようです。今でも理解できていないのですが、UIViewの初期化の勉強をもう少ししないといけませんね。

コードから初期化する場合はinit(frame: CGRect)を使い、ストーリーボードを使って初期化する場合はinit(coder: NSCoder)なんで、「// MARK: Initializers」のカテゴリーを作ってその下に加えます。

    
    //MARK: Initialization

    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)
    }

次にオブジェクト・ライブラリから「Horizontal Stack View」を選択して、「Stack View」のイメージの下に設置します。

このジェネリックなUIStackViewオブジェクトのコードを自分で作ったカスタムビューのコード、RatingControlに変更する必要があります。ジェネリックなViewを選択したまま、アイデンティティ・インスペクタを開いて、「Class」を「RatingControl」に切り替えます。

f:id:yataiblue:20170327201756j:plain

カスタムUIStackViewのRaitingControlビューの上に5つの星型のボタン(UIButton)をサブビューとして設置していきます。

f:id:yataiblue:20150709182425j:plain

まずこのUIStackViewこのイニシャライザの下に「//MARK: Private Methods」を作ってUIButtonを作成するメソッドを用意します。

private func setupButtons() {
    let button = UIButton()
    button.backgroundColor = UIColor.red
}

UIButtonは、frameデータを引数として与えてボタンの初期化生成します。Stack Viewは自動的にサイズ0のボタンで位置は(0, 0)になります。UIColor.redというクラスメソッドを使って、ボタンの属性を変更します。

サイズをコンストレイントとして加えます

button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
button.widthAnchor.constraint(equalToConstant: 44.0).isActive = true

このままでは、RatingControlビューに表示されません。

Stack Viewの場合は次のメソッド「addArrangedSubview()」で組み込むことで表示されます。「self.addArrangedSubview()」のことで「self」は推測機能で省略可能です。

Xcode6までならこれで十分だったのですが、「Stack View」でサイズを確保するために「intrinsicContentsSize」メソッドをオーバーライドする必要があります。

addArrangedSubview(button)

ボタンをセットアップするメソッドをまとめると次のようにあんります

private func setupButtons() {

    let button = UIButton()
    button.backgroundColor = UIColor.red
        
  
    button.
        translatesAutoresizingMaskIntoConstraints = 
                                                 false
    button.
        heightAnchor.constraint(equalToConstant: 44.0).
            isActive = true
    button.
        widthAnchor.constraint(equalToConstant: 44.0).
            isActive = true

    addArrangedSubview(button)
}

そしてこのセットアップメソッドをイニシャライザで呼びます。

    //MARK: Initialization

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupButtons()
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)
        setupButtons()
    }

ここでラン(Cmd + R)すると赤い四角がRatingContolビューの左端に表示されます。

f:id:yataiblue:20170327204011j:plain

このボタンは表示だけではなくタップすることで反応する機能がいるので、ボタンのアクションメソッドをコードします。

RatingControl.swiftの最後「}」直前に次のリファレンスを入れます。

// MARK: Button Action

func ratingButtonTapped(button: UIButton) {
    print("Button pressed