【问题标题】:How to hide status bar only on smaller devices?如何仅在较小的设备上隐藏状态栏?
【发布时间】:2019-03-14 15:16:29
【问题描述】:

我已经在这个问题上转了转。我只想在小于 iPhone 6 的设备上隐藏状态栏。This 答案很好,但代码现在已弃用并引发错误。

我遵循了this 帖子上的所有建议(这很有帮助),并且我有工作代码,但我必须复制并粘贴到每个视图控制器上。这似乎是个坏主意。它当然不遵守 DRY 方法。

这是适用于单个视图控制器的代码:

class Step1SplashVC: UIViewController {

var hideStatusBar: Bool = false

override var prefersStatusBarHidden: Bool { return true }

override func viewDidLoad() {
    super.viewDidLoad()

    let screenSize = Int(UIScreen.main.bounds.width)

    print("screen size:", screenSize)

    if screenSize <= 320 {
        print("device is too small. need to hide status bar")
        hideStatusBar = true
        setNeedsStatusBarAppearanceUpdate()
    }

我的问题是,我该如何重构它,这样我就不会复制和粘贴到我项目中的每个视图控制器(我总共有大约 35 个视图控制器)?

我尝试为 UIViewController 创建一个扩展,但它一直抛出错误。

这是错误的代码:

extension UIViewController {

    private struct Holder {
        static var hideStatusBar: Bool = false
    }

    var screensize: Bool {
        get {
            return Int(UIScreen.main.bounds.width) <= 320
        }

        set {
            Holder.hideStatusBar = true
        }
    }

    override var prefersStatusBarHidden: Bool { return true }
}

我得到的错误是:

属性不会覆盖其超类中的任何属性

所以我创建扩展的努力没有奏效。

如何隐藏小型设备的状态栏,而无需将代码复制并粘贴到每个视图控制器上?

谢谢!!

【问题讨论】:

  • 如果prefersStatusBarHidden 总是返回true...,我从你的代码中不太明白hideStatusBar 是如何工作的?
  • @shim 它不起作用。我开始对计算属性进行编码,但被“覆盖变量”部分卡住了。我没有完成“设置”部分的计算属性代码。

标签: ios swift


【解决方案1】:

将您编写的代码(适用于单个视图控制器)放入BaseViewControllerUIViewController 的子类:

class BaseViewController: UIViewController {

    var hideStatusBar: Bool = false

    override var prefersStatusBarHidden: Bool { return true }

    override func viewDidLoad() {
        super.viewDidLoad()

        let screenSize = Int(UIScreen.main.bounds.width)

        print("screen size:", screenSize)

        if screenSize <= 320 {
            print("device is too small. need to hide status bar")
            hideStatusBar = true
            setNeedsStatusBarAppearanceUpdate()
        }
    }
}

然后您可以在项目中的每个视图控制器上继承BaseViewController(替换class XYZViewController: UIViewController),并实现super.viewDidLoad(),例如:

class Step1SplashVC: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //Whatever you want, specific to each VC
    }
}

【讨论】:

  • 所以我仍然需要将子类添加到每个 VC 中,但我不必将所有相同的代码复制到每个 VC 中。只需在每个 VC 上进行子类化,我就可以开始了,对吧?
  • 完全正确 - 而不是你的 VC 子类化 UIViewController 你所做的就是继承你的自定义 BaseViewController
  • 感谢您的代码。我现在了解子类化的概念以及如何将其应用于这种特殊情况。这是有道理的。
【解决方案2】:

扩展不能/不应该覆盖它们扩展的类的属性/方法; see more on that here

或者,您可以将UIViewController 子类化并在子类中实现prefersStatusBarHidden,但是您必须将该子类应用于您的所有视图控制器。

还请注意,例如,如果您的应用程序的流程以 UINavigationController 为中心,您可能能够在其单个子类中而不是在每个 UIViewController 中实现您的更改。

使用UIViewController 子类化的示例(您可能希望以不同的方式构建您的实现):

class MyViewControllerBaseClass: UIViewController {
    override var prefersStatusBarHidden: Bool {
        return shouldHideStatusBar 
    }

    var shouldHideStatusBar = true
}

// ……… meanwhile in some other file…

class SomeViewController: MyViewControllerBaseClass {
    // this class now inherits the above property and the implementation of prefersStatusBarHidden
}

您也可以将检查屏幕大小的代码放在基类中。

【讨论】:

  • 啊。子类化。这对我来说是一个新领域。你能详细说明吗?也许给一些示例代码?
  • 更新了一个简单的例子
【解决方案3】:

您可以简单地在AppDelegate.swift 中隐藏状态栏。只需要三个步骤:

1) 在Info.plist 中添加新行。

密钥:View controller-based status bar appearance

值:No

2) 现在在AppDelegate.swift 中添加两个变量来获取宽度和高度,如下所示:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    //----- These lines should be added
    public var screenWidth: CGFloat {
        return UIScreen.main.bounds.width
    }
    public var screenHeight: CGFloat {
        return UIScreen.main.bounds.height
    }
    //------ End
}

3) 现在您有了设备屏幕的大小,并且您有权隐藏状态栏。在AppDelegate.swift 你有这样的功能(默认它在顶部,你的第一个功能在AppDelegate.swift):

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

在此功能中,您只需检查一次屏幕尺寸,如果它小于 320(小于 iPhone SE),则隐藏状态栏如下:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        //----- These lines should be added
        if(self.screenWidth < 320) {
            UIApplication.shared.isStatusBarHidden = true
        }
        //------ End

        return true
    }

就是这样。

通过这种方式,您只需检查一次屏幕大小和隐藏/显示状态栏。

希望有用。也对不起我的英语。

【讨论】:

  • 不幸的是,这行不通。有几个问题。 1. 通过将 plist 键 View controller-based status bar appearance 设置为 NO,我不再能够为单个视图控制器设置显示。 2. UIApplication.shared.isStatusBarHidden = true 在 iOS 9 中已弃用。
【解决方案4】:

var screenHeight: CGFloat = UIScreen.main.bounds.size.height

if screenHeight < 667 {
    UIApplication.shared.isStatusBarHidden = true
}

【讨论】:

  • 不幸的是,这行不通。 UIApplication.shared.isStatusBarHidden = true 在 iOS 9 中已弃用。
猜你喜欢
  • 2019-05-12
  • 2015-07-05
  • 2014-12-04
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多