【Xcode/Swift】同じパーツなら一つのコードで管理すればいいじゃないか (Outlet Collection)

今回の記事は同じ機能を持たせたいパーツ(ボタンとか)をひとつのコードで管理する実装方法を解説します、コードをスッキリさせられる & 管理もしやすくなり一石二鳥です。

開発環境

今回は以下の環境で実装しています

Mac OS ver12.4
Swift ver5.6
Xcode ver13.3

プロジェクト作成、Storyboardの装飾

まずはプロジェクトを作成して以下のようにStoryboardを装飾しましょう。

今回付け加えたいアクションとして、

  • ボタンを全て角丸にしたい
  • 押されたボタンのテキストをLabelに表示させたい

の二つにしましょう。

コードと紐付け、アクション機能の実装

ボタンをそれぞれプログラムと紐づけた場合

ボタンを各自プログラムと紐付けて実装した場合はこうなります。

GIFが載せられなくなったので画像ですみません、、、
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var firstButton: UIButton!
    @IBOutlet weak var secondButton: UIButton!
    @IBOutlet weak var thirdButton: UIButton!
    @IBOutlet weak var forthButton: UIButton!
    @IBOutlet weak var fifthButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
    }
    
    private func setupView() {
        firstButton.layer.cornerRadius = 20.0
        secondButton.layer.cornerRadius = 20.0
        thirdButton.layer.cornerRadius = 20.0
        forthButton.layer.cornerRadius = 20.0
        fifthButton.layer.cornerRadius = 20.0
    }
    
    @IBAction func firstAction(_ sender: Any) {
        label.text = "こんにちは"
    }
    
    @IBAction func secondAction(_ sender: Any) {
        label.text = "Hello"
    }
    
    @IBAction func thirdAction(_ sender: Any) {
        label.text = "Bonjour"
    }
    
    @IBAction func forthAction(_ sender: Any) {
        label.text = "Hola"
    }
    
    @IBAction func fifthAction(_ sender: Any) {
        label.text = "你好"
    }
    
}

実現したい機能自体はこれで作れますが、コードが冗長化(長くなる)して見辛くなってしまいます。

今回はこれを一つのコードでまとめて管理していくという実装に切り替えるやり方を解説します。


一つのコードで管理する場合 (OutletCollection)

一つのコードで管理する場合、ボタンをプログラムと紐づける時にConnectionをOutlet Collectionに変更する必要があります。

一つ繋げたら、他のボタンにもドラッグして繋げていきます。

Action接続も同じように接続しましょう。

ひとくちメモ

ボタンをタグで管理する場合、

@IBAction func buttonAction(_ sender: UIButton) {

}

という感じで、senderにUIButtonを指定する必要があります(デフォルト値はAny)

後で登場しますが、今回はsender.tagと記述する必要があるためAnyではなくUIButtonを指定してあげる必要があります。


Buttonにタグ付け

ボタンを一つのコードで管理する場合、各ボタンにタグ番号というものをつけます。(理由は後述します)

なので今回は上のボタンから順に(1 , 2 , 3 , 4 , 5)とつけていきましょう。


ここまで出来たらまずは以下コードをコピペしてください(安心安全の丸投げ)

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    @IBOutlet var button: [UIButton]!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
    }
    
    private func setupView() {
        //ボタンを角丸にする
        button.forEach({ $0.layer.cornerRadius = 20.0 })
    }
    
    //ボタンが押された時のアクション
    @IBAction func buttonAction(_ sender: UIButton) {
        //タグを使ってどのボタンが押されたか判定を行う
        switch sender.tag {
        case 1:
            label.text = "こんにちは"
        case 2:
            label.text = "Hello"
        case 3:
            label.text = "Bonjour"
        case 4:
            label.text = "Hola"
        case 5:
            label.text = "你好"
        default:
            break
        }
    }
    
}

【sender.tag】 = 先程Storyboardで設定した各ボタンのタグ番号です、それをSwitch文で条件分岐させて押されたボタン毎に表示するlabelのテキストを変更しています。

全体イメージ

ビルドをして挙動を確認してみてください、押されたボタン毎にLabelの表示テキストが変更されるはずです。

ひとくちメモ

今回のように、プログラムの動きを変えずにソースコードを変更することをリファクタリングといいます。

以下サイトに分かりやすく書かれていたので参考にしてください。

まとめ

今回は以上です、出来るだけコードはシンプルにまとめられるように実装していきましょう!