Swiftで上タブを手軽に実装する方法12選

Swiftプログラムのスクリーンショットと上タブのイラストSwift
この記事は約26分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Swiftでの上タブの実装は、アプリの利用者にとって直感的で使いやすいインターフェースを提供するために非常に有効です。

この記事を読めば、Swiftで上タブを実装する方法をマスターすることができるようになります。

上タブの基本的な実装からカスタマイズ、さらには注意点と対処法まで、具体的なサンプルコードと共に解説します。

●Swiftと上タブについて

SwiftはAppleが開発したプログラミング言語で、iOS、macOSなどのアプリケーション開発に広く使用されています。

その読みやすく、効率的なコーディングが可能な特性から、多くの開発者に愛されています。

○Swiftの基本

Swiftのコードは、シンプルで直感的です。

初心者でも学びやすく、経験者でもその効率の良さと安全性を高く評価しています。

□Swiftの特徴

Swiftには、型安全という特徴があります。これは、変数や定数に入るデータの型を明確にすることで、コードのエラーを減らし、読みやすさを向上

させるものです。

また、オプショナルという機能を利用することで、nullの扱いを安全に、そして効率的に行うことができます。

□SwiftでのUIの構築方法

SwiftでのUI構築は、コードだけでなく、Interface Builderを使用した視覚的な設計も可能です。

ドラッグアンドドロップでコンポーネントを配置し、属性を設定するだけで、直感的に画面をデザインできます。

○上タブの利点とは?

上タブは、アプリケーションの異なるセクションや機能間でユーザーを簡単にナビゲートさせるためのUI要素です。

それぞれのタブは、異なる内容や機能を持ち、タブをタップすることで簡単に切り替えが可能です。

□ユーザー体験向上のための上タブ

上タブの利用は、ユーザーの操作を最小限に抑える助けとなります。

それぞれ一目でわかるようになっており、必要な情報や機能へのアクセスが直感的に行えます。

これにより、ユーザーはアプリケーションを迷わず、効率的に使用することができるようになります。

●上タブの基本的な実装方法

Swiftで上タブを実装するときの基本的な手法は、UITabBarControllerを使用する方法です。

これは、iOSアプリ開発における標準的な手法であり、簡単に複数のビューコントローラをタブ切り替え式のインターフェースに統合することができます。

○サンプルコード1:基本的な上タブの作成

このコードではUITabBarControllerを使って基本的な上タブを作成しています。

import UIKit

class FirstViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .red
        self.title = "タブ1"
    }
}

class SecondViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .blue
        self.title = "タブ2"
    }
}

class TabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let firstVC = FirstViewController()
        let secondVC = SecondViewController()

        firstVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
        secondVC.tabBarItem = UITabBarItem(tabBarSystemItem: .more, tag: 1)

        self.viewControllers = [firstVC, secondVC]
    }
}

このコードを実行すると、2つのタブ「タブ1」と「タブ2」が表示され、それぞれの背景色が赤と青に設定されています。

タブをタップすると、それぞれのビューコントローラーが表示されます。

○サンプルコード2:デフォルトのタブ選択

アプリの起動時に特定のタブを選択状態にしたい場合は、selectedIndexプロパティを利用します。

このプロパティには、タブのインデックス番号(0から始まる)を指定することで、該当するタブが選択された状態でアプリが起動します。

class TabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let firstVC = FirstViewController()
        let secondVC = SecondViewController()

        firstVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
        secondVC.tabBarItem = UITabBarItem(tabBarSystemItem: .more, tag: 1)

        self.viewControllers = [firstVC, secondVC]
        self.selectedIndex = 1  // 「タブ2」をデフォルトで選択
    }
}

このコードを実行すると、アプリが起動した際に「タブ2」がデフォルトで選択された状態になります。

●上タブのカスタマイズ方法

Swiftでの上タブのカスタマイズ方法には多くの選択肢があります。

今回は、タブのデザインの変更、アニメーションの追加、そしてアイコンの追加に焦点を当てて解説していきます。

○サンプルコード3:タブのデザイン変更

Swiftでの上タブのデザインを変更するには、UITabBarのプロパティをカスタマイズすることが一般的です。

下記のコードは、タブの背景色や選択時の色を変更する方法を表しています。

class TabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // タブバーの背景色を設定
        self.tabBar.barTintColor = .black

        // 選択されていないタブのアイテムの色を設定
        self.tabBar.unselectedItemTintColor = .white

        // 選択されたタブのアイテムの色を設定
        self.tabBar.tintColor = .yellow
    }
}

このコードを実行すると、タブバーの背景が黒色、選択されていないタブのアイテムの色が白色、選択されたタブのアイテムの色が黄色になります。

○サンプルコード4:タブのアニメーション付与

タブをタップした際のアニメーションを追加することで、ユーザー体験を向上させることができます。

下記のサンプルコードでは、タブがタップされた際に少し拡大するアニメーションを実装しています。

extension TabBarController: UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        guard let tabBarIndex = tabBarController.selectedIndex as Int? else { return }
        let selectedTab = tabBarController.tabBar.items![tabBarIndex]
        UIView.animate(withDuration: 0.2, animations: {
            selectedTab.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
        }) { _ in
            UIView.animate(withDuration: 0.2) {
                selectedTab.transform = CGAffineTransform.identity
            }
        }
    }
}

このコードを実行すると、タブがタップされると0.2秒間で1.2倍に拡大し、その後0.2秒間で元の大きさに戻るアニメーションが追加されます。

○サンプルコード5:タブのアイコン追加

上タブにアイコンを追加することで、視覚的にタブの内容を理解しやすくなります。

ここでは、タブにアイコンを追加する基本的な方法を紹介します。

class TabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let firstVC = FirstViewController()
        let secondVC = SecondViewController()

        // タブアイコンの設定
        firstVC.tabBarItem.image = UIImage(named: "icon1")
        secondVC.tabBarItem.image = UIImage(named: "icon2")

        self.viewControllers = [firstVC, secondVC]
    }
}

このコードでは、icon1icon2という名前のアセットを使用して、それぞれのタブにアイコンを設定しています。

これにより、タブに表示されるテキストの隣にアイコンが表示されるようになります。

●上タブの応用例

Swiftにおける上タブの応用例を深堀りします。

カスタマイズや基本的な実装方法がわかったら、次に進んで多様な使い方や実装方法を知ることで、より柔軟なアプリケーション開発が可能となります。

○サンプルコード6:タブ間でのデータの受け渡し

アプリケーションを使用する中で、あるタブから別のタブにデータを受け渡したい場面があります。

下記のサンプルコードでは、そのようなデータの受け渡し方法を実装しています。

class FirstViewController: UIViewController {
    var dataToPass: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        dataToPass = "データの例"
    }

    @IBAction func moveToSecondTab() {
        if let secondVC = self.tabBarController?.viewControllers?[1] as? SecondViewController {
            secondVC.receivedData = dataToPass
            self.tabBarController?.selectedIndex = 1
        }
    }
}

class SecondViewController: UIViewController {
    var receivedData: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        if let data = receivedData {
            print(data) // "データの例"と出力
        }
    }
}

このコードでは、FirstViewControllerからSecondViewControllerにデータを渡している。

moveToSecondTab関数を実行すると、SecondViewControllerにデータが受け渡され、データの内容が出力されます。

○サンプルコード7:動的にタブを追加・削除

タブの内容や数が固定されていない場合、動的にタブを追加や削除する必要があります。

下記のサンプルコードは、動的にタブを操作する方法を表しています。

class DynamicTabBarController: UITabBarController {

    func addNewTab() {
        let newVC = UIViewController()
        newVC.view.backgroundColor = .white
        newVC.tabBarItem.title = "新しいタブ"
        var currentViewControllers = self.viewControllers
        currentViewControllers?.append(newVC)
        self.viewControllers = currentViewControllers
    }

    func removeLastTab() {
        var currentViewControllers = self.viewControllers
        currentViewControllers?.removeLast()
        self.viewControllers = currentViewControllers
    }
}

addNewTab関数を使うことで新しいタブを追加し、removeLastTab関数で最後のタブを削除することができます。

○サンプルコード8:スクロールによるタブの切り替え

ユーザーがアプリケーションを使う中で、スワイプやスクロールによってタブを切り替えることは、直感的な操作感を求める場合に非常に有効です。

この方法をSwiftで実装する方法を次のサンプルコードで解説します。

import UIKit

class ScrollableTabBarController: UITabBarController, UIScrollViewDelegate {

    var scrollView: UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // UIScrollViewの設定
        scrollView = UIScrollView(frame: view.bounds)
        scrollView.delegate = self
        scrollView.isPagingEnabled = true
        scrollView.contentSize = CGSize(width: view.bounds.width * CGFloat(viewControllers!.count), height: view.bounds.height)

        // 各ViewControllerをUIScrollViewに追加
        for (index, vc) in viewControllers!.enumerated() {
            vc.view.frame = CGRect(x: view.bounds.width * CGFloat(index), y: 0, width: view.bounds.width, height: view.bounds.height)
            scrollView.addSubview(vc.view)
        }

        self.view.addSubview(scrollView)
    }

    // スクロールの位置に応じてタブを切り替える
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let page = Int(scrollView.contentOffset.x / view.bounds.width)
        self.selectedIndex = page
    }
}

このコードでは、UITabBarControllerを継承したScrollableTabBarControllerという新しいクラスを作成しています。

ここでは、UIScrollViewを使用して、その上に各タブの内容を配置し、スクロールが完了した位置で現在のタブを更新しています。

このコードを実行すると、ユーザーは左右にスワイプすることでタブの内容を切り替えることができるようになります。

スクロールの終了位置に応じて、タブの選択も更新されます。

○サンプルコード9:タブのバッジ表示

アプリケーションの中で、あるタブに未読メッセージや通知がある場合、タブの上にバッジを表示してユーザーにその情報を伝えることはよくあります。

下記のサンプルコードでは、タブにバッジを表示しています。

class BadgeTabBarController: UITabBarController {

    func setBadge(at index: Int, value: String?) {
        self.tabBar.items?[index].badgeValue = value
    }
}

このコードでは、UITabBarControllerを継承したBadgeTabBarControllerという新しいクラスを作成しています。

このクラス内のsetBadge関数を使用することで、指定したタブにバッジを表示することができます。

例えば、setBadge(at: 1, value: "5")というコードを実行すると、2番目のタブに「5」というバッジが表示されます。

バッジの値をnilにすることで、バッジを非表示にすることもできます。

○サンプルコード10:ネストされた上タブの実装

SwiftでのUI制作では、ネストされた上タブを実装するケースが増えてきています。ネストされた上タブとは、上タブの内部にさらにタブを持つ構造を指します。

このような複雑なタブ構造は、情報のカテゴライズや階層化に役立ちます。

ここでは、ネストされた上タブをSwiftで実装する方法を紹介します。

import UIKit

class NestedTabBarController: UIViewController {

    // 外部の上タブ
    let mainTabBarController = UITabBarController()

    // 内部の上タブ
    let nestedTabBarController1 = UITabBarController()
    let nestedTabBarController2 = UITabBarController()

    override func viewDidLoad() {
        super.viewDidLoad()

        // 内部の上タブ1の設定
        let vc1 = UIViewController()
        vc1.view.backgroundColor = .red
        let vc2 = UIViewController()
        vc2.view.backgroundColor = .blue
        nestedTabBarController1.viewControllers = [vc1, vc2]

        // 内部の上タブ2の設定
        let vc3 = UIViewController()
        vc3.view.backgroundColor = .green
        let vc4 = UIViewController()
        vc4.view.backgroundColor = .yellow
        nestedTabBarController2.viewControllers = [vc3, vc4]

        // 外部の上タブに内部の上タブをセット
        mainTabBarController.viewControllers = [nestedTabBarController1, nestedTabBarController2]
        view.addSubview(mainTabBarController.view)
    }
}

このコードではNestedTabBarControllerというクラスを作成し、その中にmainTabBarControllerという外部の上タブを持っています。

さらに、この外部の上タブには、nestedTabBarController1nestedTabBarController2という2つの内部の上タブが配置されています。

このコードを実行すると、画面上部に外部の上タブが表示され、その各タブを選択することで、それぞれの内部の上タブを操作することができます。

例えば、外部の上タブの1つ目を選択すると、赤と青のバックグラウンドカラーを持つ2つの内部の上タブが表示されます。

○サンプルコード11:外部ライブラリを用いた上タブの拡張

Swiftのコミュニティでは、多くの有用なライブラリが提供されており、上タブの実装をさらに洗練されたものにするための外部ライブラリも存在します。

例として、XYPagerTabというライブラリを使って、上タブのカスタマイズを行う方法を解説します。

このライブラリを利用することで、タブのデザインやアニメーション、スクロール動作などを細かく設定することができます。

まずは、ライブラリをインストールします。

pod 'XYPagerTab'

次に、ライブラリを利用して上タブをカスタマイズするサンプルコードです。

import UIKit
import XYPagerTab

class CustomTabBarController: XYPagerTabController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // タブのタイトルを設定
        let titles = ["タブ1", "タブ2", "タブ3"]
        setTitles(titles)

        // 各タブのViewControllerを設定
        let vc1 = UIViewController()
        let vc2 = UIViewController()
        let vc3 = UIViewController()
        setViewControllers([vc1, vc2, vc3])

        // タブのデザインをカスタマイズ
        customizeTabDesign()
    }

    func customizeTabDesign() {
        // ここでタブのデザインやアニメーションをカスタマイズする
    }
}

このコードでは、XYPagerTabControllerを継承したCustomTabBarControllerクラスを作成しています。

このクラス内で、タブのタイトルや表示するViewController、さらにタブのデザインやアニメーションをカスタマイズすることができます。

このコードを実行すると、カスタマイズされたデザインの上タブが表示され、それぞれのタブを選択することで対応するViewControllerが表示されます。

○サンプルコード12:上タブとサイドメニューの組み合わせ

アプリケーションのユーザビリティを向上させるために、上タブとサイドメニューを組み合わせる方法が考えられます。

SwiftでこのようなUIを実装する場合、複数のコンポーネントを組み合わせて動作させる必要があります。

サイドメニューは、多くの情報や機能をコンパクトにまとめて提供するための一つの手段です。

上タブと組み合わせることで、ユーザーに直感的な操作性と高いアクセシビリティを提供することができます。

まず、上タブとサイドメニューの基本的な構造を考えます。

上タブは通常のUIViewControllerの一部として配置され、サイドメニューは主に左側や右側からスワイプすることで表示される形になります。

import UIKit

class CombinedViewController: UIViewController {

    // 上タブ部分の実装
    let tabBarController = UITabBarController()

    // サイドメニュー部分の実装
    var sideMenu: UIView!
    var isSideMenuOpen = false

    override func viewDidLoad() {
        super.viewDidLoad()

        // 上タブの設定
        let tab1 = UIViewController()
        tab1.view.backgroundColor = .red
        let tab2 = UIViewController()
        tab2.view.backgroundColor = .blue
        tabBarController.viewControllers = [tab1, tab2]
        view.addSubview(tabBarController.view)

        // サイドメニューの設定
        sideMenu = UIView(frame: CGRect(x: -250, y: 0, width: 250, height: self.view.bounds.height))
        sideMenu.backgroundColor = .gray
        view.addSubview(sideMenu)

        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe))
        swipeRight.direction = .right
        view.addGestureRecognizer(swipeRight)

        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe))
        swipeLeft.direction = .left
        view.addGestureRecognizer(swipeLeft)
    }

    @objc func handleSwipe(gesture: UISwipeGestureRecognizer) {
        if gesture.direction == .right {
            // サイドメニューを表示
            UIView.animate(withDuration: 0.5) {
                self.sideMenu.frame.origin.x = 0
            }
            isSideMenuOpen = true
        } else if gesture.direction == .left && isSideMenuOpen {
            // サイドメニューを非表示
            UIView.animate(withDuration: 0.5) {
                self.sideMenu.frame.origin.x = -250
            }
            isSideMenuOpen = false
        }
    }
}

このコードは、上タブとサイドメニューを組み合わせたUIを実現するためのものです。

UITabBarControllerを使って上タブを作成し、サイドメニューはUIViewとして実装しています。

スワイプジェスチャーを利用して、サイドメニューを表示・非表示にします。

このコードを実行すると、画面上部に上タブが表示され、左側から右にスワイプすることでグレーのサイドメニューが表示されます。

再度、右から左にスワイプするとサイドメニューは非表示になります。

●注意点と対処法

Swiftで上タブを実装する際には、多くの利点がありますが、その一方で考慮すべき注意点や問題点がいくつか存在します。

これらの問題を理解し、適切な対処法を取ることで、ユーザーフレンドリーで安定したアプリケーションを作成することができます。

○上タブの配置に関する注意

上タブを配置する際の最も一般的な問題は、デバイスの画面サイズや解像度の違いによるレイアウトの崩れです。

特に、異なるiOSデバイス間での表示の違いは、ユーザー体験の低下を引き起こす可能性があります。

対処法として、Auto Layoutを使用することで、異なるデバイスサイズや画面の向きに柔軟に対応するレイアウトを実現することができます。

下記のサンプルコードでは、上タブの高さをデバイスのサイズに合わせて自動調整する方法を表しています。

// 上タブの高さを設定
let tabBarHeight: CGFloat = 50
tabBarController.tabBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    tabBarController.tabBar.heightAnchor.constraint(equalToConstant: tabBarHeight)
])

このコードを使用すると、上タブの高さが一定の値になり、デバイスのサイズに関係なく一貫した表示を保つことができます。

○メモリリークの対処法

上タブを使用する際には、特に多数のタブを持つ場合、不要なメモリの使用やメモリリークに注意する必要があります。

対処法として、弱参照(weak reference)や非保持参照(unowned reference)を使用して、循環参照を避けることができます。

また、定期的にメモリの使用状況を監視し、不要なオブジェクトを解放することも重要です。

class SampleViewController: UIViewController {
    weak var delegate: AnotherClassDelegate?
    // その他の実装
}

このコードでは、delegateプロパティを弱参照として宣言しています。

これにより、SampleViewControllerとデリゲートオブジェクト間の循環参照を防ぐことができます。

○レスポンスの最適化

多数のタブを持つアプリケーションでは、タブ間の移動やコンテンツのロードに時間がかかる場合があります。

このような遅延は、ユーザー体験の低下を引き起こす可能性があります。

対処法として、非同期処理や遅延読み込み(lazy loading)を使用して、コンテンツのロードを最適化することができます。

これにより、ユーザーがタブを切り替えたときに、スムーズにコンテンツを表示することができます。

// 遅延読み込みの実装例
lazy var content: SomeExpensiveObject = {
    return SomeExpensiveObject()
}()

このコードを使用すると、contentが実際にアクセスされたときにのみSomeExpensiveObjectのインスタンスが作成されます。

これにより、初回の読み込み時間を短縮することができます。

まとめ

Swiftで上タブを実装することは、多くのユーザー体験の向上をもたらすことができます。

この記事では、Swiftにおける上タブの基本的な実装方法からカスタマイズ、さらには応用例までを網羅的に紹介しました。

しかし、その際に考慮すべき注意点や問題点も存在するため、それらに適切に対応することが非常に重要です。

Auto Layoutの利用やメモリ管理の工夫、そしてレスポンスの最適化など、Swiftでの上タブ実装における様々なテクニックを学ぶことができたかと思います。

これらの知識を元に、より使いやすく、快適なアプリケーションを作成することができるでしょう。

初心者から上級者まで、この記事を通じてSwiftでの上タブ実装のプロセスを理解し、実際の開発に活かすことを強くおすすめします。

今後のアプリ開発に、本記事が役立つことを心より願っています。