iOS13及以上如何将XIB自定义视图置于所有ViewController之上?
解决方案
不需要修改AppDelegate或SceneDelegate来实现播放器视图的持久显示——这两个文件负责应用/场景的生命周期管理,视图层级的需求在容器控制器(如你的TabBarController)中处理更合理。
iOS 13+的可行方案如下:
方案一:将播放器视图添加到自定义TabBarController的视图层级
这是最直接的方式,因为TabBarController是所有子ViewController的容器,它的视图不会随Tab切换而被替换或隐藏。
- 创建
UITabBarController的子类,比如CustomTabBarController - 在子类中初始化并添加自定义播放器视图,确保它处于视图层级的最上层:
import UIKit // 自定义播放器视图示例 class AudioPlayerView: UIView { override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .lightGray // 这里添加播放器的UI元素(播放按钮、进度条等) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } class CustomTabBarController: UITabBarController { private let playerView = AudioPlayerView() override func viewDidLoad() { super.viewDidLoad() setupPlayerView() } private func setupPlayerView() { playerView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(playerView) // 设置AutoLayout约束,让播放器固定在顶部安全区下方 NSLayoutConstraint.activate([ playerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), playerView.leadingAnchor.constraint(equalTo: view.leadingAnchor), playerView.trailingAnchor.constraint(equalTo: view.trailingAnchor), playerView.heightAnchor.constraint(equalToConstant: 60) ]) // 确保播放器视图在所有子视图最上层,避免被切换的ViewController视图覆盖 view.bringSubviewToFront(playerView) } }
- 将Storyboard中的TabBarController类设置为
CustomTabBarController,或在代码中初始化该子类作为根控制器。
方案二:将播放器视图添加到UIWindow(全局显示)
如果需要播放器在所有页面(包括push出来的ViewController)都保持显示,可以将视图直接添加到UIWindow上:
在SceneDelegate的scene(_:willConnectTo:options:)方法中添加:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) self.window = window // 初始化TabBarController作为根控制器 let tabBarController = UITabBarController() // 配置你的两个子ViewController... window.rootViewController = tabBarController // 添加播放器到Window let playerView = AudioPlayerView() playerView.translatesAutoresizingMaskIntoConstraints = false window.addSubview(playerView) NSLayoutConstraint.activate([ playerView.topAnchor.constraint(equalTo: window.safeAreaLayoutGuide.topAnchor), playerView.leadingAnchor.constraint(equalTo: window.leadingAnchor), playerView.trailingAnchor.constraint(equalTo: window.trailingAnchor), playerView.heightAnchor.constraint(equalToConstant: 60) ]) window.makeKeyAndVisible() }
注意事项
- 方案一中,播放器仅在TabBarController管理的页面显示;方案二则是全局显示,根据你的需求选择。
- 若使用导航控制器,需注意播放器视图与导航栏的布局冲突,可调整约束让播放器位于导航栏下方。
- 不需要修改AppDelegate/SceneDelegate的核心逻辑,仅在需要全局添加视图时,在SceneDelegate中做一次性初始化即可。
内容的提问来源于stack exchange,提问作者PaulS
相关产品推荐
相关产品推荐

