admin管理员组文章数量:1201570
My iOS and Mac Catalyst app uses a dark color theme by default, regardless of the system color theme. When the app presents a modal view controller (a popup or a popover) on iOS, the background of that view is dark for its entire visible lifespan. But on macOS, if the system color theme is light, the background of the popup is initially white until the view loads, and the background of a popover changes to white as it dismisses:
In my modal view controllers, I'm overriding the color theme, as well as manually setting the background color. This does the job on iOS but has no effect on macOS:
override func viewDidLoad() {
super.viewDidLoad()
self.overrideUserInterfaceStyle = .dark
self.view.backgroundColor = myColor
}
I'm setting overrideUserInterfaceStyle
that way on the main view controller; that handles the main view but doesn't affect popups and popovers.
I tried setting overrideUserInterfaceStyle
on the app's window object, but that had no effect. I tried setting it in application:didFinishLaunchingWithOptions:
for the AppDelegate, in scene:willConnectTo:options:
for the SceneDelegate and even in viewDidLoad
for the modal view controller.
In the xib files that I use for popups and popovers, I tried setting the background of the top-level view to my desired background color, but that had no effect. (Normally I set them to transparent, which is fine in iOS.)
Apparently macOS displays an empty view before loading the xib and before running viewDidLoad. Is there a "deeper" way I can set the color to avoid this ugly visual effect?
UPDATE
Here's the minimum code that demonstrates the problem:
let test = UIViewController()
App.mainViewController.present(test, animated: true)
This results in a white popup window if the Mac is using the light color theme, even though the main view controller's overrideUserInterfaceStyle
is set to dark. I tried setting overrideUserInterfaceStyle
at various levels, but with no change:
App.window?.overrideUserInterfaceStyle = .dark
App.mainViewController.overrideUserInterfaceStyle = .dark
let test = UIViewController()
test.overrideUserInterfaceStyle = .dark
test.view.rootView.overrideUserInterfaceStyle = .dark
test.view.window?.overrideUserInterfaceStyle = .dark
App.mainViewController.present(test, animated: true)
If I set the background color of the popup's view, that works, but it initially appears white and then the background color takes effect, as in the animation above.
let test = UIViewController()
test.view.backgroundColor = App.bgColor
App.mainViewController.present(test, animated: true)
On iOS, all I needed was to set overrideUserInterfaceStyle
on the main view controller.
My iOS and Mac Catalyst app uses a dark color theme by default, regardless of the system color theme. When the app presents a modal view controller (a popup or a popover) on iOS, the background of that view is dark for its entire visible lifespan. But on macOS, if the system color theme is light, the background of the popup is initially white until the view loads, and the background of a popover changes to white as it dismisses:
In my modal view controllers, I'm overriding the color theme, as well as manually setting the background color. This does the job on iOS but has no effect on macOS:
override func viewDidLoad() {
super.viewDidLoad()
self.overrideUserInterfaceStyle = .dark
self.view.backgroundColor = myColor
}
I'm setting overrideUserInterfaceStyle
that way on the main view controller; that handles the main view but doesn't affect popups and popovers.
I tried setting overrideUserInterfaceStyle
on the app's window object, but that had no effect. I tried setting it in application:didFinishLaunchingWithOptions:
for the AppDelegate, in scene:willConnectTo:options:
for the SceneDelegate and even in viewDidLoad
for the modal view controller.
In the xib files that I use for popups and popovers, I tried setting the background of the top-level view to my desired background color, but that had no effect. (Normally I set them to transparent, which is fine in iOS.)
Apparently macOS displays an empty view before loading the xib and before running viewDidLoad. Is there a "deeper" way I can set the color to avoid this ugly visual effect?
UPDATE
Here's the minimum code that demonstrates the problem:
let test = UIViewController()
App.mainViewController.present(test, animated: true)
This results in a white popup window if the Mac is using the light color theme, even though the main view controller's overrideUserInterfaceStyle
is set to dark. I tried setting overrideUserInterfaceStyle
at various levels, but with no change:
App.window?.overrideUserInterfaceStyle = .dark
App.mainViewController.overrideUserInterfaceStyle = .dark
let test = UIViewController()
test.overrideUserInterfaceStyle = .dark
test.view.rootView.overrideUserInterfaceStyle = .dark
test.view.window?.overrideUserInterfaceStyle = .dark
App.mainViewController.present(test, animated: true)
If I set the background color of the popup's view, that works, but it initially appears white and then the background color takes effect, as in the animation above.
let test = UIViewController()
test.view.backgroundColor = App.bgColor
App.mainViewController.present(test, animated: true)
On iOS, all I needed was to set overrideUserInterfaceStyle
on the main view controller.
1 Answer
Reset to default 1I consider this a Mac Catalyst bug. I strongly urge you to file a bug report with Apple. Include a simple sample app that demonstrates the problem. All you need is a bare-bones iOS app that adds a button that presents a second view controller. Set the main scene's window's overrideUserInterfaceStyle
property to dark
. Setup the project with a Mac Catalyst destination. Include instructions to run the app while the device is in light-mode.
I did a lot of digging into this issue. The problem stems from the fact that under Mac Catalyst, when presenting a modal view controller with either .formSheet
or .pageSheet
, the app actually creates a new, private scene with its own window that displays the view controller. This new scene is what is displaying that white pane briefly before the actual view controller is displayed.
I attempted to work around the issue with a line such as:
vc.presentationController!.traitOverrides.userInterfaceStyle = .dark
where vc
is the view controller being presented. Despite setting this, the white pane still appears briefly.
I did find one hacky workaround. The solution is to display the view controller as a popover instead of the default .formSheet
. The following code gives reasonable results:
let vc = SomeViewController()
#if targetEnvironment(macCatalyst)
vc.modalPresentationStyle = .popover
vc.isModalInPresentation = true // optional
vc.preferredContentSize = .init(width: 600, height: 600) // matches normal formSheet
vc.popoverPresentationController?.sourceView = self.view
// Calculate where the top-center of the popover should be to get the popover centered in place
let origin = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY - vc.preferredContentSize.height / 2)
vc.popoverPresentationController?.sourceRect = .init(origin: origin, size: .zero)
#endif
self.present(vc, animated: true)
When run on a Mac, the view controller is shown as a properly sized and positioned popover. There is no more flash of white.
When run on an iPhone/iPad, the normal presentation is made.
If you have a lot of places in your code where you present a form sheet, you may wish to create some sort of UIViewController
extension method that encapsulates this workaround so you don't need to replicate the code in more than one place.
本文标签: iosHow to set initial background color of Mac Catalyst windowsStack Overflow
版权声明:本文标题:ios - How to set initial background color of Mac Catalyst windows? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738607748a2102450.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
self.overrideUserInterfaceStyle = .dark
to all of the app's windows instead of separate view controllers. – HangarRash Commented Jan 21 at 20:06