『入る学科間違えた高専生』の日記

プログラミングのコードを書いたりする予定です。あとは日記等。あといつまで高専生やねん

FloatingPanel を UITabBarController から表示する

はじめに

ウッ...タイトルが難しい.やりたいことはこうじゃ...

https://user-images.githubusercontent.com/9856514/139561045-0fff143b-02a3-42ed-a591-0ac5b17e0ef2.gif

Twitter のこんな感じでセミモーダルを UITabBarController を配置してるときにも表示したいっていう感じ.
今回はセミモーダルを実装するときに私がよく使っている FloatingPanel を使って実装した時に発生したクラッシュを交えて備忘録的なご紹介ができればと思います.

github.com

環境

  • Xcode 13.0
  • FloatingPanel 2.4.0

準備

プロジェクトは作ったね?いいね.

f:id:nanashinodonbee:20211031083015p:plain

FloatingPanel はとりあえず Swift Package Manager で追加しておきました.
CocoaPods でも Carthage でも自分が使いたいものを使ってインストールしてください.

SceneDelegate はとりあえず使わない想定なので削除しておきました.

ちなみに今回使用する UITabBarController は CustomTabBarController としてサブクラスとして作成しました.

f:id:nanashinodonbee:20211031084917p:plain

FloatingPanel の使い方は色々あると思うので探してみてください.本体自体の README.md にもめっちゃ詳細に書かれていたりするのでそちらを参照していただければと思います.

UITabBarController に FloatingPanel をつけてみる

純粋に FloatingPanel を UITabBarController につけてみようと思います.

CustomTabBarController.swift をこんな感じにしてみました.

import FloatingPanel
import UIKit

final class CustomTabBarController: UITabBarController {

    private lazy var floatingPanelController: FloatingPanelController = .init(delegate: self)

    override func viewDidLoad() {
        super.viewDidLoad()

        floatingPanelController.addPanel(toParent: self)
    }
}

// MARK: - FloatingPanelControllerDelegate
extension CustomTabBarController: FloatingPanelControllerDelegate {}

f:id:nanashinodonbee:20211031085915p:plain

おっと.クラッシュしてしまった...

UITabBarController displays child view controllers with a radio-style selection interface

DeepL に翻訳を任せてみました.(寝てない私は今英語を読める力がありません)
→ UITabBarControllerは、子ビューコントローラをラジオ形式の選択インターフェースで表示します。

UITabBarController の説明だった...
他にも UINavigationController UISplitViewController UITableViewController UICollectionViewController に FloatingPanel は設定できないらしいです.

解決法を探る

とりあえず雑に検索してみる.「 floatingpanel uitabbarcontroller

f:id:nanashinodonbee:20211031095430p:plain

お,それっぽい Issue だ

UITabBarController displays child view controllers with a radio-style selection interface. So FloatingPanelController doesn't work well when it's added into UITabBarViewController directly because FloatingPanelController is a chid view controller of a parent.

It's out of control from this library. Please add it to a child view controller(a tab) of UITabBarViewController or wrap UITabBarViewController with a view controller.

This sample code can be helpful for you.

https://github.com/SCENEE/FloatingPanel/issues/23#issuecomment-434907953

サンプルコードがリンク切れしてるけど,

Please add it to a child view controller(a tab) of UITabBarViewController or wrap UITabBarViewController with a view controller.

っていうところが肝っぽい.

解決方法

ちょっと補助的に SnapKit を導入してます.

ContainerViewController を追加しました.
AppDelegateUIWindow? の rootViewController に設定するコードを変更しておきます.

+ window?.rootViewController = ContainerViewController()
- window?.rootViewController = CustomTabBarController()

ContainerViewController.swift はこんな感じで addChild しておきます.

import SnapKit
import UIKit

final class ContainerViewController: UIViewController {

    private let customTabBarController: CustomTabBarController = .init()

    override func viewDidLoad() {
        super.viewDidLoad()

        addChild(customTabBarController)
        view.addSubview(customTabBarController.view)
        customTabBarController.view.snp.makeConstraints { $0.edges.equalToSuperview() }
        customTabBarController.didMove(toParent: self)
    }
}

あとは ContainerViewController 側に FloatingPanelController を設定してあげれば動くはず!!

https://user-images.githubusercontent.com/9856514/139563098-f282aad0-70bb-4167-a6ba-b909fcbdc0af.gif

もろもろ魔改造はしましたがこんな感じに UITabBarController の内側からではなく親から表示させることができました!

今回作成したコードはこちらに

bitbucket.org

(いい加減, BitBucket は OGP 対応してくれないかな...)

最後に

今回は, Twitter などでよく見られる UITabBarController の上に FloatingPanel を表示する方法を書きました.
これをやったのはたまたま自分が記事内で紹介したクラッシュに遭遇したからっていうのがありました.

ハッピーハロウィーン!!

今回はちょっと OGP 作るのサボりました... ぴえん