preferredStatusBarStyle 不执行

本文详细介绍了如何在iOS应用中设置状态栏和导航栏的样式,包括使用plist文件配置`Viewcontroller-basedstatusbarappearance`为Yes,以及将`UINavigationBar.barStyle`属性设置为UIBarStyleBlack,确保了自定义状态栏和导航栏的一致性。

1、 plist文件里 “View controller-based status bar appearance” 要设置为Yes;

2、 UINavigationBar.barStyle属性要设置为UIBarStyleBlack。(UINavigationController 包含了它自己的状态栏)

转载于:https://www.cnblogs.com/nielsen/p/5067963.html

你遇到了一个 **非常典型、但容易被忽视的 iOS 导航控制问题**: > 即使你在 `viewDidLoad` 中调用了: ```swift self.navigationController?.setNavigationBarHidden(true, animated: false) ``` 导航栏仍然“存在”或“占位”,`stickyHeader` 没有贴到屏幕顶部。 --- ## ✅ 核心结论(先说答案) > ❌ 你之所以看到“没隐藏”,根本原因很可能是: > > 🔴 **`SurveillanceCommonTableController` 是从某个父类继承而来,而它的父类在 `viewWillAppear` 或其他时机又“重新显示了导航栏”!** > > 或者: pushViewController 时导航栏状态未同步完成,导致你的设置被覆盖。 --- ## ✅ 分步排查与解决方案 ### ✅ 步骤 1:确认 `navigationController` 是否为 nil? 添加打印调试: ```swift override func viewDidLoad() { super.viewDidLoad() print("【Debug】navigationController: \(self.navigationController)") print("【Debug】isNavigationBarHidden: \(self.navigationController?.isNavigationBarHidden ?? false)") self.navigationController?.setNavigationBarHidden(true, animated: false) print("【After】isNavigationBarHidden: \(self.navigationController?.isNavigationBarHidden ?? false)") } ``` 📌 输出示例如下: ```text 【Debug】navigationController: Optional(<UINavigationController: 0x10a0...>) 【Debug】isNavigationBarHidden: false 【After】isNavigationBarHidden: true ``` ✅ 如果输出是 `true`,说明命令执行成功。 ❌ 如果 `navigationController` 是 `nil`,那你根本能控制导航栏! 👉 解决方法:确保你是通过 `UINavigationController.pushViewController(...)` 进入此页面的。 --- ### ✅ 步骤 2:检查父类是否干扰(关键!) 你说你继承的是: ```swift class DeviceListNewViewController: SurveillanceCommonTableController ``` ⚠️ 很可能这个 `SurveillanceCommonTableController` 在 `viewWillAppear` 或 `loadView` 中做了如下事情: - 强制设置 `navigationController?.setNavigationBarHidden(false)` - 设置了默认 appearance - 修改了 `edgesForExtendedLayout` - 调用了 `super.viewWillAppear()` 并在里面恢复了导航栏 🔍 查看父类源码中是否有类似代码: ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(false, animated: false) // ⚠️ 覆盖你的设置! } ``` --- ### ✅ 步骤 3:强制在 `viewDidLayoutSubviews` 再次隐藏(应急方案) 如果父类确实在后面“复活”了导航栏,你可以用这个技巧强行压制: ```swift override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 最终保险:再次隐藏 self.navigationController?.setNavigationBarHidden(true, animated: false) } ``` ⚠️ 注意:这是优雅做法,但有效。 --- ### ✅ 步骤 4:修改布局锚点 —— 依赖 `safeArea.top` 你现在这行代码有问题: ```swift make.top.equalTo(view.safeAreaLayoutGuide.snp.top) ``` 当系统认为“应该保留导航栏高度”时,`safeArea.top` 依然是 88pt(比如 iPhone 13),即使你看到导航栏。 🎯 目标:让 `stickyHeader` **真正贴近屏幕顶部 Y=0** #### ✅ 修改为使用 `topLayoutGuide` 或直接使用 `Y=0` ##### 方案 A:使用 `topLayoutGuide`(iOS 11 前兼容方式) ```swift override func tpbMakeConstraint() { stickyHeader.snp.makeConstraints { make in make.top.equalTo(self.topLayoutGuide.snp.bottom) // ← 关键:指向导航栏/状态栏底部 make.leading.trailing.equalToSuperview() make.height.equalTo(80) } ... } ``` > ✅ `topLayoutGuide` 会自动指向 `navigationBar.bottom` 或 `safeArea.top` 但如果导航栏已隐藏,它会变成 `0` 吗?一定! --- ##### ✅ 方案 B(推荐):绕过 safeArea,直接从 Y=0 开始布局 ```swift override func tpbMakeConstraint() { // 让 stickyHeader 从屏幕最顶部开始(Y=0) stickyHeader.snp.makeConstraints { make in make.top.equalToSuperview() // ← 改成 superview.top,是 safeArea! make.leading.trailing.equalToSuperview() make.height.equalTo(80) } backButton.snp.remakeConstraints { make in make.leading.equalTo(stickyHeader).offset(16) make.centerY.equalTo(stickyHeader).offset(-10) // 手动微调垂直居中 make.width.greaterThanOrEqualTo(30) } titleLabel.snp.remakeConstraints { make in make.centerX.equalToSuperview() make.centerY.equalTo(backButton) } searchButton.snp.remakeConstraints { make in make.trailing.equalTo(stickyHeader).offset(-16) make.centerY.equalTo(backButton) make.width.greaterThanOrEqualTo(30) } tableView.snp.remakeConstraints { make in make.top.equalTo(stickyHeader.snp.bottom).offset(10) make.leading.trailing.bottom.equalToSuperview() } } ``` 然后你需要手动处理状态栏避让: #### ✅ 设置状态栏为透明穿透 ```swift override func viewDidLoad() { super.viewDidLoad() // 强制隐藏导航栏 self.navigationController?.setNavigationBarHidden(true, animated: false) // 允许内容延伸到顶部 self.edgesForExtendedLayout = .top self.extendedLayoutIncludesOpaqueBars = false // 包含透明栏 self.tableView.contentInsetAdjustmentBehavior = .never } ``` 这样你的 `stickyHeader` 就能从 `(0,0)` 开始绘制,真正贴顶! --- ### ✅ 步骤 5:设置状态栏样式(可选) 为了让状态栏文字清晰可见: ```swift override var preferredStatusBarStyle: UIStatusBarStyle { return .darkContent // 黑色文字,适合浅色背景 } ``` 并在 `Info.plist` 添加: ```xml <key>UIViewControllerBasedStatusBarAppearance</key> <true/> ``` 否则该设置无效。 --- ## ✅ 最终建议完整代码片段 ```swift override func viewDidLoad() { super.viewDidLoad() // ✅ 1. 立即隐藏导航栏 self.navigationController?.setNavigationBarHidden(true, animated: false) // ✅ 2. 允许内容延伸到顶部区域 self.edgesForExtendedLayout = .top self.extendedLayoutIncludesOpaqueBars = false self.tableView.contentInsetAdjustmentBehavior = .never // ✅ 3. 清除标题和按钮 self.title = nil navigationItem.leftBarButtonItem = nil navigationItem.rightBarButtonItem = nil } override func tpbMakeConstraint() { // ✅ stickyHeader 从屏幕顶部 (Y=0) 开始 stickyHeader.snp.makeConstraints { make in make.top.equalToSuperview() make.leading.trailing.equalToSuperview() make.height.equalTo(80) } // 布局子控件... backButton.snp.remakeConstraints { make in make.leading.equalTo(stickyHeader).offset(16) make.centerY.equalTo(stickyHeader).offset(-10) // 手动调整对齐 make.width.greaterThanOrEqualTo(30) } titleLabel.snp.remakeConstraints { make in make.centerX.equalToSuperview() make.centerY.equalTo(backButton) } searchButton.snp.remakeConstraints { make in make.trailing.equalTo(stickyHeader).offset(-16) make.centerY.equalTo(backButton) make.width.greaterThanOrEqualTo(30) } tableView.snp.remakeConstraints { make in make.top.equalTo(stickyHeader.snp.bottom).offset(10) make.leading.trailing.bottom.equalToSuperview() } } // ✅ 状态栏文字颜色 override var preferredStatusBarStyle: UIStatusBarStyle { return .darkContent } ``` --- ## ✅ 效果验证 | 验证项 | 方法 | |------|------| | 是否贴顶 | 用 Xcode View Hierarchy Debugger 查看 `stickyHeader.frame.origin.y == 0` | | 导航栏是否隐藏 | `po self.navigationController?.navigationBar.isHidden` 应为 `true` | | safeArea.top 是否仍偏移 | 可忽略,因为我们再依赖它 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值