Set StatusBar Color for Extensions in UIActivityVi

2020-04-14 07:50发布

问题:

Following situation given:

iOS 8+ App (mainly Swift). StatusBar is set to View controller-based status bar appearance. Within the App multiple UIActivityViewControllers are used to display sharing options.

The Problem: Some sharing activities have wrong StatusBar colors. Those are the device installed extensions shown when using an UIActivityViewController. Here: the sharing activities, like e.g. WhatsApp, Tumblr, Skype.

What I want to achieve: Default StatusBarStyle for this App is .LightContent to fit a local UIAppearance (tinting a base NavigationController class). Remote FullScreen Controllers should get .Default StatusBarStyle while Modal dialogs should keep the current style (.LightContent).

I tested each and every possible combination and now I'm stuck.

Code in the Main View Controller (tabbed App):

    override func preferredStatusBarStyle() -> UIStatusBarStyle {
        return .LightContent
    }

    override func prefersStatusBarHidden() -> Bool {
        return false
    }

    override func childViewControllerForStatusBarStyle() -> UIViewController? {
        guard let presentedViewController = presentedViewController else {
            return nil
        }

        switch presentedViewController {
        case is SLComposeViewController: // Social Sharing, e.g. Facebook, WhatsApp, Reminders etc.
            // let rawPresentationStyle = presentedViewController.modalPresentationStyle.rawValue
            // rawPresentationStyle == 17 (0x11) is undocumented Raw Value for SLComposeViewController dialogs
            return presentedViewController
        case is UIActivityViewController:
            // i.e. "More" Activity, UIActivityViewController internally uses presentViewController again to show "More" View
            // presentedViewController.modalPresentationStyle != presentedViewController.presentedViewController.modalPresentationStyle (e.g. .Popover to .OverCurrentContext)
            let presentedStyle = presentedViewController.presentedViewController?.modalPresentationStyle // UIActivity > presented
            if presentedStyle == .OverFullScreen {
                return presentedViewController
            }
        default:
            break
        }

        return nil // use local preferredStatusBarStyle
    }

The code is working fine. Verified the switch to be correct at every single step. However, SLComposeViewController initiates a XPC Remote View: SLRemoteComposeViewController together with _UIRemoteView.

Both don't set the .modalPresentationStyle, so there is no way to obtain this value to decide whether to give control to presentedViewController or not.

So basically said, no matter if the XPC Remote View is modal (dimming over current context) or FullScreen, the StatusBar becomes .Default when returning control to self.presentedViewController.

I was able to track it down to the XPC. modalPresentationStyle of SLComposeViewController is of undocumented style 17 (0x11).

Has anybody figured out how to set a correct StatusBar for the social sharing together with UIActivityViewController?

Edit: I also tried to set View controller-based status bar appearance to no. With this setting preferredStatusBarStyle and childViewControllerForStatusBarStyle: are not called at all, as per documentation. But anyway, this won't work, no matter if the Status Bar is .LightContent or .Default. It's either the remote Modal activity is wrong or the remote FullScreen activity. Of course remote XPC Views are not under developer's control. From what I learned the extension developers (Facebook, WhatsApp etc) have the same problem the other way round: They are unable to control the StatusBar neither..

Any radr I'm missing?

Edit2: Changed title, I am also aware of modalPresentationCapturesStatusBarAppearance.

I found this interesting blog post from the engineering team at Tumblr, dated some time in 2014, they have unfixable problems with the StatusBar when creating their share extension, too. See http://engineering.tumblr.com/post/97658880154/what-we-learned-building-the-tumblr-ios-share - pointing to: http://openradar.appspot.com/radar?id=6397505050771456

Workaround

None so far. Neither Info.plist keys nor view controller methods worked, and we couldn’t even get a handle to the keyboard window the way that applications can usually accomplish using private API (Sam Giddins nearly went insane trying. Thanks Sam!). Here’s hoping for a way to do this in iOS 8.1.

I got nearly insane trying, too ;)