4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UIContentUnavailableConfigurationでStateに応じて画面を手軽に切り替える

Posted at

はじめに

WWDC23(2023 Apple Worldwide Developers Confere)でUIKitの新機能が色々発表され、その中でも今後よく使っていくであろうEmpty State(UIContentUnavailableConfiguration)について備忘録としてまとめました。

公式ドキュメント

Empty Stateの概要

機能概要

以下公式発表ではEmpty Stateとして紹介されていますが、UIContentUnavailableConfigurationというUIKitのストラクチャです。Stateに応じて画面に画像/ラベル/ボタンを表示・切り替えることができます。

公式紹介ビデオ

特性と使い方

ViewControllerのcontentUnavailableConfigurationに対し様々なUIContentUnavailableConfigurationのStateを設定することにより、画面に画像/ラベル/ボタンを表示したり切り替えたりすることができます。
画像等を非表示にするためには明示的にnilを設定する必要があります。

実装例

import UIKit

class SecondViewController: UIViewController {
    
    // Stateを用意
    enum UnavailableState {
        case normal
        case empty
        case loading
        case error
    }
    
    @IBOutlet weak var tableView: UITableView!
    
    var screenState: UnavailableState = .loading
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 使用するセルをテーブルビューに登録する
        self.tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "tableViewCell")
        
        // ステータスを指定
        self.setupUnavailableConfiguration(state: .normal)
    }
    
    private func setupUnavailableConfiguration(state: UnavailableState) {
        self.screenState = state
        
        switch state {
            
        case .normal:
            // 画像・テキスト・ボタンを非表示
            self.contentUnavailableConfiguration = nil
            
        case .empty:
            var config = UIContentUnavailableConfiguration.search()
            config.text = "No Data"
            config.secondaryText = "Please try again"
            var buttonConfig =  UIButton.Configuration.filled()
            buttonConfig.title = "Retry"
            config.button = buttonConfig
            config.buttonProperties.primaryAction = UIAction(handler: { _ in
                // button action
            })
            self.contentUnavailableConfiguration = config
            
        case .loading:
            var config = UIContentUnavailableConfiguration.loading()
            config.text = "Please wait..."
            config.textProperties.font = .boldSystemFont(ofSize: 18)
            self.contentUnavailableConfiguration = config
            
        case .error:
            var config = UIContentUnavailableConfiguration.empty()
            config.image = UIImage(systemName: "exclamationmark.triangle")
            config.imageProperties.tintColor = .red
            config.text = "Error"
            config.textProperties.color = .red
            self.contentUnavailableConfiguration = config
        }
    }
}

extension SecondViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // 用意するセルの個数
        return self.screenState == .normal ? 50 : 0
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // テーブルビューの枠内に表示するセルを指定する
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell") as? TableViewCell else {
            return UITableViewCell()
        }
        
        // セルのレイアウト設定
        cell.setCellLabel(cellIndex: indexPath.row.description)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // セル押下時の挙動
        let storyboard = UIStoryboard(name: "ThirdView", bundle: nil)
        guard let thirdViewController = storyboard.instantiateViewController(withIdentifier: "thirdView") as? ThirdViewController else {
            return
        }
        
        guard let cell = tableView.cellForRow(at: indexPath) as? TableViewCell else {
            return
        }
        
        thirdViewController.randomString = cell.cellLabel.text ?? ""
        self.navigationController?.pushViewController(thirdViewController, animated: true)
    }   
}

画面キャプチャ

State 正常 Loading Empty Error
    画面     normal.png loading.png empty.png error.png

まとめ

UIContentUnavailableConfigurationを使用するとローディング中やエラーの場合などに専用のビューを作成する必要がないのでとても魅力的ですね。アプリ開発において必須というわけではなさそうですが、知っておいて損は無い技術だと感じました。
WWDCではいくつもの新しい項目が発表され、追いつけていないどころか1年周回遅れになりそうですが、空き時間にコツコツ勉強していきたいところです。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?