SwiftUI 设置状态栏样式

6

我一直在尝试设置我的SwiftUI应用程序中的状态栏为浅色文本,因为它有一个暗色背景。

我在几个网站上找到了这个解决方案,但是无法使其正常工作。

HostingController.swift

import Foundation
import UIKit
import SwiftUI

class HostingController : UIHostingController {
    override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
    }
}

这将返回一个错误,出现在类声明行:Reference to generic type 'UIHostingController' requires arguments in <...>,建议修复为Insert '<<#Content: View#>>'。应用此修复会导致错误Use of undeclared type '<#Content: View#>'
然后您需要更改SceneDelegate.swift文件中的window.rootViewControllerSceneDelegate.swift

...

// Create the SwiftUI view that provides the window contents.
        let contentView = Login()

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = HostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }

window.rootViewController这一行会抛出错误:传递给不接受参数的调用的参数

有人有什么想法吗?看起来只是为了设置状态栏颜色而感到很麻烦,我想这应该是一个相当普遍的需求。

4个回答

6

您的HostingController需要一个具体类型的rootView:

class HostingViewController<Content: View>: UIHostingController<Content> {

    @objc override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

然后将其用作 func scene(_ scene:UIScene,willConnectTo ...中的rootViewController:

let contentView = ContentView()
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        
        window.rootViewController = HostingViewController(rootView: AnyView(contentView.environmentObject(SessionStore())))
        self.window = window
        window.makeKeyAndVisible()
    }

很遗憾,在画布上您看不到任何区别,但请在模拟器上尝试。


谢谢。这很有效。但是我必须删除我的 environmentObject 使其工作 HostingController(rootView: contentView.environmentObject(SessionStore()) 否则需要修复为 HostingController(rootView: contentView.environmentObject(SessionStore()) as! ContentView),然后运行时会抛出 SIGABRT 错误。 - iShaymus
尝试这样声明:HostingViewController: UIHostingController<AnyView>,然后将您的rootview擦除为AnyView HostingController(rootView: AnyView(contentView.environmentObject(SessionStore())))。 - LuLuGaGa
window.rootViewController = AnyView HostingController(rootView: AnyView(contentView.environmentObject(SessionStore()))) throws the error Cannot assign value of type 'AnyView.Type' to type 'UIViewController?' - iShaymus
这不是我想要的。请查看我的编辑答案。 - LuLuGaGa
像魔法一样运行良好:window.rootViewController = HostingController(rootView: AnyView(contentView.environmentObject(SessionStore()))) - iShaymus
我有点晚了,但你可以更好地使用泛型: - Roland.R

6

扩展 UIHostingController 的另一种方式是保持泛型的 Content 类型,这样你就不必传递会话存储:

class HostingController<Content>: UIHostingController<Content> where Content: View {
    @objc override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

然后在你的场景代理中:

window.rootViewController = HostingController(rootView: contentView)

这个很棒。我的问题是:除非泛型正确,否则View和onTapGesture不起作用。我也不需要@objc。 这让我也可以做到:if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = HostingController( rootView: homeView.onTapGesture { window.endEditing(true) } ) self.window = window window.makeKeyAndVisible() } - Madhava Jay

3
在iOS 14中,您只需要在Info.plist文件中更改/添加2个键:

输入图像描述


1
这是截至iOS 14的正确答案。不再需要编写代码来实现此功能。请按照上述在“Info.plist”文件中指示的更改设置。 - iShaymus
1
这里有一个视频展示如何更新 Info.plist: https://youtu.be/w-I5I8POMSI - Richard H
这个效果很好,很干净!请注意,这将改变整个应用程序的状态栏。如果您需要根据视图来进行更改,您可能想要查看这个链接:https://github.com/xavierdonnellon/swiftui-statusbarstyle - undefined

0

我晚了一点,但你可以更好地使用泛型:

class HostingController<ContentView: View>: UIHostingController<ContentView> {
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .darkContent
    }
}

这样可以让你将任何视图传递给HostingController,即使使用.environmentObject()视图修饰符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接