如何在Swift 3

时间:2016-08-03 10:12:09

标签: ios swift uiviewcontroller uistatusbar ios-statusbar

我正在使用Xcode 8.0 beta 4。

在以前的版本中,UIViewController具有设置状态栏样式的方法

public func preferredStatusBarStyle() -> UIStatusBarStyle

然而,我发现它改为"只能变换"在Swift 3中。

public var preferredStatusBarStyle: UIStatusBarStyle { get } 

如何提供在我的UIViewController中使用的样式?

35 个答案:

答案 0 :(得分:438)

这是iOS 7及更高版本的首选方法

在您的应用程序Info.plist中,将“查看基于控制器的状态栏外观”设置为YES。

Override preferredStatusBarStyle in each of your view controllers。例如:

override var preferredStatusBarStyle: UIStatusBarStyle {     
      return .lightContent
}

如果preferredStatusBarStyle根据视图控制器内部发生变化的情况(例如,滚动位置或显示的图像是否暗)返回不同的首选状态栏样式,那么您将需要当该状态发生变化时,请致电setNeedsStatusBarAppearanceUpdate()

如果您使用导航控制器并且希望使用每个视图控制器的首选状态栏样式,请参阅https://stackoverflow.com/a/41026726/1589422

版本7之前的iOS,已弃用的方法

Apple has deprecated this,因此将来会被删除。使用上面的方法,以便在下一个iOS版本发布时不必重写它。

如果您的应用程序支持在您的应用程序Info.plist中,请将“查看基于控制器的状态栏外观”设置为NO。

appDelegate.swiftdidFinishLaunchingWithOptions功能中,添加:

UIApplication.shared.statusBarStyle = .lightContent

答案 1 :(得分:135)

最新更新(Xcode 10+ / Swift 4.2 +)

对于愿意理解过去几年中存在的不同方法背后的逻辑的人来说,这篇文章完好无损。同时,从 Xcode 10,Swift 4.2 first approach is deprecated开始,不再受支持(如果您尝试使用 将不会生效)。仍然会提供您的信息,以便更好地理解Plist.info标志和自定义练习背后的原因。

重要说明

了解自定义状态栏外观的两种方法非常重要。它们是不同的,不应混合。

第一种方法 - 整个应用程序的一种颜色(自iOS7以来已弃用)

在info.plist中,您可以找到或创建一个名为

的密钥

View controller-based status bar appearance

并将其设置为

它做什么?它基本上建立了一个设置,表明在您的应用程序中,状态栏外观不是由每个视图控制器单独定义。理解这一点非常重要。这意味着对于所有屏幕,您可以为整个应用设置统一设置。有两种设置:default,即白色背景上的黑色文字,或lightContent,即黑色背景上的白色文字。

设置其中一个(所有屏幕的一个设置):

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    application.statusBarStyle = .lightContent // .default
    return true
}

这样您就不需要在每个视图控制器上重新建立此设置。但是,您始终可以使用此方法自动更改外观。

第二种方法 - 每个视图控制器的单独颜色

这是相反的。要使其工作,请继续info.plist并设置

View controller-based status bar appearance

这样,每当打开一个新的视图控制器时,如果您在所需的每个UIViewController实例中插入此实现,则会单独设置状态栏样式:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent // .default
}

您与第一个相同,为状态栏设置暗或亮样式,为每个视图控制器设置个别。

UIKit在两种情况下获取此属性:

  1. 在初始化屏幕时,正在准备UI。
  2. 在代码中调用setNeedsStatusBarAppearanceUpdate()
  3. 在后一种情况下,您有资格通过以下代码操作状态栏外观:

    var isDark = false {
        didSet {
            setNeedsStatusBarAppearanceUpdate()
        }
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return isDark ? .lightContent : .default
    }
    
    func toggleAppearance() {
       isDark.toggle()
    }
    

    然后,无论何时拨打toggleAppearance(),都会触发状态栏样式更改。

    第三种方法 - 哈克!

    有一个hack可以直接访问状态栏:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
        if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView {
            statusBar.backgroundColor = UIColor.blue
        }
    
        return true
    }
    

    为什么要破解?如果您需要状态栏颜色而不是黑色或白色,则使用未记录的API。您使用KVC获取statusBar对象并设置其背景颜色。您通过这种方式获得的对象是UIStatusBar,它派生自UIView,因此自然支持backgroundColor属性。这很脏,不合法,但到目前为止,它是为状态栏设置自定义颜色的唯一方法(不考虑UINavigationBar方法,它允许完全自定义导航栏+状态栏外观)。它可能会导致您的应用被拒绝。但也许你很幸运。如果你是,在某些复杂的情况下(比如嵌套,子导航和视图控制器的层次结构),这可能是自定义状态栏外观的唯一或至少不那么麻烦的方法(例如,使其透明)< / p>

    Xcode 10 +,Swift 4.2

    不再有其他选择:开发人员应让每个视图控制器定义状态栏外观,方法是将标志设置为 YES (或省略此操作,因为它是YES默认)并遵循上述说明。

    <强>加成

    基于Hack的解决方案,您可能(尽管不鼓励)在复杂的环境中使用,以便在任何阶段自愿更改状态栏外观。颜色方面,以下扩展方法完全按照常规方法完成。您可以根据需要进行调整。

    extension UIViewController {
        func setStatusBarStyle(_ style: UIStatusBarStyle) {
            if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView {
                statusBar.backgroundColor = style == .lightContent ? UIColor.black : .white
                statusBar.setValue(style == .lightContent ? UIColor.white : .black, forKey: "foregroundColor")
            }
        }
    }
    

答案 2 :(得分:128)

您可以尝试覆盖返回的值,而不是设置它。该方法声明为{get},因此只需提供一个getter:

 override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

如果您有条件地设置此选项,则需要致电setNeedsStatusBarAppearanceUpdate(),以便在您准备就绪时为更改设置动画

答案 3 :(得分:99)

Swift 3&amp; 4,iOS 10&amp; 11,Xcode 9&amp; 10
对我来说,这种方法不起作用:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

当我习惯了每个视图控制器时,但这很有效:

  • 在文件info.list中,添加行View controller-based status bar appearance并设置为NO

  • 接下来在appdelegate:

    UIApplication.shared.statusBarStyle = .lightContent
    

答案 4 :(得分:26)

如果您想将statusBar的颜色更改为白色,对于UINavigationController中包含的所有观看次数,请在AppDelegate内添加:

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

    UINavigationBar.appearance().barStyle = .blackOpaque
    return true
}

此代码:

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

适用于UIViewControllers中包含的UINavigationController,因为编译器会查找statusBarStyle的{​​{1}},而不是UINavigationController其中包含的statusBarStyle ViewControllers

希望这可以帮助那些没有成功接受答案的人!

答案 5 :(得分:25)

您需要在Info.plist文件中添加以下密钥:

Fill ,布尔值设置为 Rectangle

在appdelegate类中,在返回之前使用Fill方法。

View controller-based status bar appearance

根据要求更改NOdidFinishLaunchingWithOptions

答案 6 :(得分:24)

如果要在视图出现后随时更改状态栏样式,可以使用:

  • 在文件info.list中添加行:查看基于控制器的状态栏外观并将其设置为

    var viewIsDark = Bool()
    
    func makeViewDark() {
    
        viewIsDark = true
        setNeedsStatusBarAppearanceUpdate()
    }
    
    func makeViewLight() {
    
        viewIsDark = false
        setNeedsStatusBarAppearanceUpdate()
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
    
        if viewIsDark {
            return .lightContent 
        } else {
            return .default 
        } 
    }
    

答案 7 :(得分:13)

您也可以在故事板中执行此操作

  1. 在info.plist中创建一个新条目“查看基于控制器的状态栏外观”将其设置为“是”。
  2. 转到故事板,然后选择要更改的导航控制器。单击Storyboard文档大纲部分导航栏(故事板上的左侧面板)
  3. 转到右侧面板,然后单击属性部分
  4. 在导航栏部分下,您将看到样式。选择您想要的样式(默认为黑色,黑色为白色)
  5. 您必须为每个导航控制器执行此操作。但是,该导航控制器下的任何视图都会将所有视图的状态栏样式/颜色更改为您刚刚选择的那个。我发现这个选项更好,因为你可以立即看到你的结果,而不必在每个视图控制器中添加额外的代码行。

    enter image description here

    (在所有Swift项目中使用Xcode 8.3.3完成)

答案 8 :(得分:8)

首先,您需要添加一行密钥:<body ng-app="mainApp"> <div ng-controller="myController"> <select> <option ng-repeat="person in persons.data">{{person}}</option> </select> </div> </body> 和值View controller-based status bar appearanceNO文件。之后,在控制器中添加2个功能,只有控制器才能生效:

Info.plist

答案 9 :(得分:6)

处理导航栏时,状态栏文本颜色似乎有一个小问题。

如果您希望.plist条目将基于控制器的状态栏外观设置为YES,则当您有彩色导航栏时,它有时会无效。

例如:

override func viewWillAppear(_ animated: Bool) {
    let nav = self.navigationController?.navigationBar
    nav?.barTintColor = .red
    nav?.tintColor = .white
    nav?.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    setNeedsStatusBarAppearanceUpdate()
}

override var preferredStatusBarStyle: UIStatusBarStyle {return .lightContent}

即使您在AppDelegate中设置了以下代码,上面的代码也不会起作用:

UIApplication.shared.statusBarStyle = .lightContent

对于仍在苦苦挣扎的人,显然它会以某种方式判断导航栏中的状态栏是否需要亮或暗。所以,我设法通过在viewWillAppear中添加以下行来解决这个问题:

nav?.barStyle = UIBarStyle.black

当条形样式为黑色时,它会侦听被覆盖的变量。希望这有助于某人:)

答案 10 :(得分:6)

Swift 3

在Info.plist中添加一行名为“查看基于控制器的状态栏外观”并将其值设置为No

class YourViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        UIApplication.shared.statusBarStyle = .lightContent //or .default
        setNeedsStatusBarAppearanceUpdate()

    }

}

答案 11 :(得分:5)

Xcode 8.3.1,Swift 3.1

  1. 在info.plist中创建一个新条目&#34;查看基于控制器的状态栏外观&#34;将它设置为&#34; NO&#34;。

  2. 打开AppDelegate.swift并在&#34; didFinishLaunchingWithOptions&#34;中添加这些行。方法:

  3. application.statusBarStyle = .lightContent

答案 12 :(得分:5)

对于希望在以下平台上更改所有视图控制器状态栏的用户:iOS 11,Swfit 4解决方案非常简单。

1) Info.plist添加:

  

基于视图控制器的状态栏外观->否

2) XCode slect项目的左侧> 目标>选择您的项目>在General>部署信息下>选择状态栏样式:浅

如果您只想更改一个viewcontroller 的状态栏,请在viewDidLoad上添加:

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

答案 13 :(得分:5)

雨燕5

要为在https://stackoverflow.com/a/40066798/2082851 PRAVEEN 的答案添加更多详细信息,我想提供我的实现。它支持灵活性来自定义每个控制器的状态栏。

总体而言,我们将创建一个BaseViewController来处理statusBarStyle属性。创建新控制器时,使其成为该基本控制器的子类。

只要要更改状态外观,就只需要更新此属性。 状态栏样式将立即更新。

实施

class BaseViewController: UIViewController {

    var statusBarStyle: UIStatusBarStyle = .default {
        didSet {
            setNeedsStatusBarAppearanceUpdate()
        }
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return statusBarStyle
    }
}

演示

class ViewController: BaseViewController, UIScrollViewDelegate {

    let scrollView = UIScrollView()
    ... 
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        UIView.animate(withDuration: 0.3) {
            if scrollView.contentOffset.y > 30 {
                self.statusBarStyle = .darkContent
            } else {
                self.statusBarStyle = .lightContent
            }
        }
    }
}

enter image description here

2。 UINavigationController

对于UINavigationController,这是一种特殊情况,您可以采用以下任一解决方案:

解决方案A:使用消息分发替代

由于UINavigationController是NSObject并继承自ObjectiveC,因此它的方法是message dispatch,您可以覆盖它们。

extension UINavigationController {
   open override var preferredStatusBarStyle: UIStatusBarStyle {
      return topViewController?.preferredStatusBarStyle ?? .default
   }
}

解决方案B:创建UINavigationController子类

如果您已经有一个自定义UINavigationController(通常需要控制更多要求),那么这是最适合您的解决方案。

final class NavigationController: UINavigationController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle ?? super.preferredStatusBarStyle
    }
}

答案 14 :(得分:4)

要添加@Krunal https://stackoverflow.com/a/49552326/4697535

如果您使用的是UINavigationController,则preferredStatusBarStyleUIViewController无效。

Xcode 10和Swift 4。

设置自定义UINavigationController

示例:

class LightNavigationController: UINavigationController {

   open override var preferredStatusBarStyle: UIStatusBarStyle {
       return .lightContent
   }
}

为应用程序级别的解决方案使用扩展程序:

extension UINavigationController {

  open override var preferredStatusBarStyle: UIStatusBarStyle {
      guard let index = tabBarController?.selectedIndex else { return .default }
      switch index {
      case 0, 1, 2: return .lightContent // set lightContent for tabs 0-2
      default: return .default // set dark for tab 3
      }
  }
}

答案 15 :(得分:4)

Swift 4.0 请在“didFinishLaunchingWithOptions launchOptions:”Appdelegate类中使用此代码

UIApplication.shared.statusBarStyle = .lightContent
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to: #selector(setter: UIView.backgroundColor)){
  statusBar.backgroundColor = UIColor.black
}

答案 16 :(得分:4)

以下是关于状态栏样式更改的Apple Guidelines/Instruction

如果要设置状态栏样式,应用程序级别,请在UIViewControllerBasedStatusBarAppearance文件中将NO设置为.plist。并在您的appdelegate&gt; didFinishLaunchingWithOptions添加以下ine(以编程方式,您可以从app delegate中执行此操作)。

目标C

[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

<强>夫特

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    application.statusBarStyle = .lightContent
    return true
}

如果您要在视图控制器级别设置状态栏样式,请按照以下步骤操作:

  1. 如果您只需要在UIViewController级别设置状态栏样式,请在UIViewControllerBasedStatusBarAppearance文件中将YES设置为.plist
  2. 在viewDidLoad添加功能 - setNeedsStatusBarAppearanceUpdate

  3. 覆盖视图控制器中的preferredStatusBarStyle。

  4. 目标C

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self setNeedsStatusBarAppearanceUpdate];
    }
    
    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        return UIStatusBarStyleLightContent;
    }
    

    <强>夫特

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setNeedsStatusBarAppearanceUpdate()
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    

    根据状态栏样式设置级别设置.plist的值。

    enter image description here

答案 17 :(得分:3)

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

这对我有用:)我的导航控制器中嵌入了导航控制器,而导航栏却隐藏了。我想在应用程序中的某些视图上设置状态栏灯。

答案 18 :(得分:3)

这对我有用

View controller-based status bar外观设置为plist中的 NO ,然后在UIViewController viewDidAppear中添加以下行

UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.lightContent, animated: true)

答案 19 :(得分:3)

swift 3

如果在Info.plist中查看基于控制器的状态栏外观= YES

然后将此扩展名用于所有NavigationController

    extension UINavigationController
    {
        override open var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
         }
     }

如果没有UINavigationController且只有UIViewController,那么使用下面的代码:

    extension UIViewController
    {
        override open var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
         }
     }

答案 20 :(得分:2)

您可以使用名为“shouldStatusBarDark”的bool属性来切换状态栏颜色。您还可以在滚动时更新其值以更改状态栏颜色。

 var shouldStatusBarDark = false {
     didSet {
         setNeedsStatusBarAppearanceUpdate()
     }
 }

 override var preferredStatusBarStyle: UIStatusBarStyle {
     return shouldStatusBarDark ? .default : .lightContent
 }

 func scrollViewDidScroll(_ scrollView: UIScrollView) {
     let offSetY = scrollView.contentOffset.y
     if offSetY > 50 {
         UIView.animate(withDuration: 0.4, animations: {
             self.navView.alpha = 1
             self.shouldStatusBarDark = true
         })
     } else {
         UIView.animate(withDuration: 0.4, animations: {
             self.navView.alpha = 0
             self.shouldStatusBarDark = false
         })
     }
 }

答案 21 :(得分:2)

Swift 4 +

表示白色状态栏文字:

navigationController.navigationBar.barStyle = .blackTranslucent

答案 22 :(得分:2)

这些答案中的大多数都是相同的东西,但是当使用深色背景时,它们实际上都没有为我解决启动屏幕的问题。

我在info.plist中用以下内容解决了这个问题,该内容产生了一个浅色的状态栏。

<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>

答案 23 :(得分:2)

  1. 选择轻内容 enter image description here

  2. 将带有基于视图控制器的状态栏外观添加到.plist enter image description here

答案 24 :(得分:1)

Xcode 10或更高版本

无需代码,只需执行以下步骤即可。

  

如果要在整个应用程序中更改状态栏。

  1. 从项目导航器(左侧面板)中选择项目。
  2. 选择目标。
  3. 选择“常规”标签。
  4. 查找部署信息。
  5. 将状态栏样式更改为(对于深色背景“浅” ,浅背景“默认”

不要忘记info.plist的更改

  1. 选择信息标签
  2. 将此密钥添加到您的plist文件“基于视图控制器的状态栏外观” = NO

运行项目并进行检查。

我在Swift 5和Xcode 10.2中的项目

答案 25 :(得分:1)

如果您使用模式演示,则需要设置:

viewController.modalPresentationCapturesStatusBarAppearance = true

答案 26 :(得分:0)

使用WebkitView

Swift 9.3 iOS 11.3

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    @IBOutlet weak var webView: WKWebView!
    var hideStatusBar = true

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setNeedsStatusBarAppearanceUpdate()
        let myURL = URL(string: "https://www.apple.com/")
        let myRequest = URLRequest(url: myURL!)
        UIApplication.shared.statusBarView?.backgroundColor = UIColor.red

         webView.load(myRequest)

    }
}

extension UIApplication {

    var statusBarView: UIView? {
        return value(forKey: "statusBar") as? UIView
    }

}

答案 27 :(得分:0)

请在您的info.plist中添加以下行,然后只有您才能实现

“基于视图控制器的状态栏外观=否”

并将以下代码段添加到您的代码中,然后查看输出

 unset spring_profiles_active 

答案 28 :(得分:0)

对于目标C,只需在应用程序中添加此行didFinishLaunch方法

UIApplication.sharedApplication.statusBarStyle = UIStatusBarStyleLightContent;

答案 29 :(得分:0)

如果收到警告:在iOS 9.0中不建议使用'statusBarStyle'设置:使用-[UIViewController preferredStatusBarStyle] ,然后使用以下代码将状态栏设置为亮或暗:

//To set the status bar to white
self.navigationController?.navigationBar.barStyle = .black //or .blackTranslucent

//To set the status bar to black
self.navigationController?.navigationBar.barStyle = .default

这不会使您的navBar更改为纯粹指示样式,因此不会相应地更改状态栏。

NB。您需要确保在info.plist中进行设置。

View controller-based status bar appearance to YES

答案 30 :(得分:0)

在iOS 13中,您可以使用.darkContent UIStatusBarStyle属性显示暗状态栏

答案 31 :(得分:0)

如果您仍然无法根据方法更改状态栏样式

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

您可以尝试使用此方法:

override viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationController?.navigationBar.barStyle = .black
}

答案 32 :(得分:0)

我得到了:

  

覆盖var必须与其封闭类型

一样可访问

通过添加public来解决此问题:

override public var preferredStatusBarStyle: UIStatusBarStyle {
    get {
        return .lightContent
    }
}

在Swift3 iOS10上。

答案 33 :(得分:0)

我也在为此而苦苦挣扎,因此,如果要呈现FULLSCREEN模态视图控制器,请确保将.modalPresentationStyle设置为.fullscreen,然后在呈现的视图控制器上,只需覆盖{{1 }}到.preferredStatusBarStyle

所以:

.lightContent

在自定义视图控制器上,覆盖状态栏样式:

let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = .fullScreen // <=== make sure to set navigation modal presentation style
present(navigationController, animated: true, completion: nil)

答案 34 :(得分:-1)

Swift 3

要在应用中设置相同的导航栏外观,可以在AppDelegate.swift中执行此操作:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        setupNavigationBarAppearence()
        return true
    }



private func setupNavigationBarAppearence(){
        let navigationBarAppearace = UINavigationBar.appearance()
        navigationBarAppearace.isTranslucent = false
        //nav bar color
        navigationBarAppearace.barTintColor = UIColor.primaryColor()
        //SETS navbar title string to white
        navigationBarAppearace.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
        //Makes the batery icon an any other icon of the device to white.
        navigationBarAppearace.barStyle = .black
    }