every Tech Blog

株式会社エブリーのTech Blogです。

UIKit アプリに Liquid Glass の検索タブを実装する

1. はじめに:Liquid Glass で変わる「検索」の体験

WWDC25 で発表された Liquid Glass は、iOS 26 の目玉となるデザインシステムです。ナビゲーションバーやタブバーがガラスのような半透明素材になり、コンテンツがその裏側に透過して見えるようになります。

見た目の変化も大きいですが、Liquid Glass がアプリの体験として特に大きく変えたのは検索です。iOS 26 では、タブバーの右端に検索アイコンが配置され、タップするとタブバー自体が検索フィールドに変わります。設定アプリや App Store など Apple 純正アプリではこの新しい検索 UI が標準になっており、ユーザーはどのアプリでも同じ操作で検索にアクセスできるようになりました。

これはサードパーティアプリにとっても重要な変更です。この新しい検索パターンを採用することで、iOS の標準的な検索体験と統一感のある UI を提供できます。

Liquid Glass の対応ポイントは多岐にわたりますが、この検索タブの変更は特にユーザー体験への影響が大きいと感じたため、既存の UIKit アプリでどう実現するかを調べて実装してみました。

SwiftUI であれば、検索タブの Liquid Glass 対応は驚くほど簡単です。

TabView {
    Tab("ホーム", systemImage: "house") { HomeView() }
    Tab(role: .search) { SearchView() }
}

Tab(role: .search) の 1 行で、タブバーの右端に検索アイコンが分離配置され、タップするとタブバー内に検索フィールドが展開する動きを実現できます。

この記事では、UIKit の UITabBarController + UINavigationController を基盤とした既存アプリに Liquid Glass の検索タブを適用する方法を紹介します。

2. ゴール:タブバー内に検索フィールドが展開する UI

実装するのは以下の動きです。

  1. タブバーの右端に検索アイコンが配置される
  2. 検索アイコンをタップすると、タブバー内に検索フィールドがスライドして展開する
  3. テキストを入力して検索できる
  4. キャンセルすると元のタブバー表示に戻る

これは iOS 26 の設定アプリや App Store で見られる標準的な動きで、UISearchTab というクラスを使って実現します。

iOS 18 で UITab API が導入されました。従来の viewControllers 配列ベースのタブ管理に代わり、UITab オブジェクトを使ってタブを構成する新しい方式です。

UISearchTabUITab のサブクラスで、検索専用のタブを表します。SwiftUI の Tab(role: .search) に対応する UIKit のクラスです。

@available(iOS 18.0, *)
private func setupWithUITabAPI() {
    // 検索以外のタブを UITab として生成
    var uiTabs: [UITab] = nonSearchItems.map { item in
        UITab(
            title: item.title,
            image: item.tabImage,
            identifier: item.identifier
        ) { _ in
            item.controller
        }
    }

    // 検索タブは UISearchTab を使う
    let searchTab = UISearchTab { [weak self] _ in
        guard let self else { return UIViewController() }
        return TabBarItemType.search.controller
    }

    uiTabs.append(searchTab)
    tabs = uiTabs
}

UISearchTab のポイントは以下の通りです。

  • タイトルや画像の指定が不要です。システムが検索アイコンを自動で提供します
  • タブバーの右端(trailing 端)に自動で分離配置されます。他のタブとは異なる位置に置かれます
  • tabs プロパティに設定するだけで、タブバー内の検索フィールド展開がシステム標準で動作します

4. 検索 ViewController の対応

UISearchTab を設定すると、タブバーに検索アイコンが表示されます。しかし、タップしたときに検索フィールドをタブバー内に展開させるには、ViewController 側の対応も必要です。

UISearchTab がタブバー内で検索フィールドを展開するには、検索コントローラーが navigationItem.searchController に設定されている必要があります。

navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false

navigationItem.titleView にカスタム配置した検索バーでは、UISearchTab のタブバー展開とは連携しません。既存のアプリで titleView ベースの検索バーを使っている場合は、navigationItem.searchController への移行が必要です。

5. iOS バージョンだけでなく Info.plist も見て分岐する

サンプルコード中で使用している LiquidGlassAvailability.isEnabled について説明します。

iOS 26 以降でも UIDesignRequiresCompatibilitytrue に設定している場合、アプリは Liquid Glass ではなく従来のデザインで表示されます。この場合、UISearchTab を使ったタブ構成にすると見た目と挙動が噛み合わなくなります。

そこで、iOS バージョンと Info.plist のフラグを両方チェックするヘルパーを用意しました。

enum LiquidGlassAvailability {
    static var isEnabled: Bool {
        guard #available(iOS 26.0, *) else {
            return false
        }
        // UIDesignRequiresCompatibility が true なら互換モード → Liquid Glass 無効
        if let requiresCompatibility = Bundle.main.object(
            forInfoDictionaryKey: "UIDesignRequiresCompatibility"
        ) as? Bool, requiresCompatibility {
            return false
        }
        return true
    }
}

判定ロジックは以下の通りです。

条件 isEnabled
iOS 25 以前 false
iOS 26+ / UIDesignRequiresCompatibility = true false
iOS 26+ / UIDesignRequiresCompatibility 未設定 or false true

なぜこれが必要か

UIDesignRequiresCompatibility は、Liquid Glass への移行を段階的に進めるための Apple 公式の仕組みです。Info.plist にこのキーを true で設定すると、iOS 26 でもアプリは従来のデザインで表示されます。つまり「iOS 26 以降 = Liquid Glass」ではないのです。

開発中は Liquid Glass を有効にして動作確認し、問題があればこのフラグを true にして一時的に互換モードに戻す、という使い方ができます。コード側もこのフラグに連動して分岐しておけば、フラグひとつで Liquid Glass の ON/OFF を切り替えられます。

Liquid Glass 対応は多岐にわたるため、ある程度長い開発期間が必要になると考えられます。他の施策の開発と並行して進められるように、このような仕組みを用意しました。

6. まとめ

UIKit アプリで Liquid Glass の検索タブを実装するための要点を整理します。

  1. UISearchTab を使うUITab のサブクラスで、SwiftUI の Tab(role: .search) に対応する UIKit のクラスです。タイトルや画像は不要で、タブバー右端への分離配置と検索フィールドの展開がシステム標準で動作します。

  2. 検索バーは navigationItem.searchController に設定するnavigationItem.titleView にカスタム配置した検索バーでは、UISearchTab のタブバー展開と連携しません。

  3. iOS バージョンだけでなく UIDesignRequiresCompatibility も見る#available だけでは不十分です。Info.plist のフラグと組み合わせた LiquidGlassAvailability.isEnabled を用意し、Liquid Glass の ON/OFF にコードが追従するようにしました。

  4. #available で後方互換を維持するUITab API は iOS 18+、automaticallyActivatesSearch は iOS 26+ です。既存の viewControllers ベースのコードと UITab API ベースのコードを分岐で共存させます。

SwiftUI への全面移行を待たなくても、UIKit アプリに段階的に Liquid Glass を取り入れることは可能です。UISearchTab はその第一歩として取り組みやすい対応だと思います。