8

I have a requirement of light content in status bar with black background, however some of the screen needs black status bar content with white background, hence I've kept View controller-based status bar appearance to YES in info.plist to adopt status bar style based on view controllers requirement.

My problem is whenever I present SFSafariViewController from any view controller it is taking black status bar content and white background by default i.e status bar style is .default everytime.

I tried overriding preferredStatusBarStyle in SFSafariViewController subclass and no look so far.

Below is my code


import UIKit
import SafariServices

extension SFSafariViewController {

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

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

class MyViewController: UIViewController, SFSafariViewControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.navigationBar.barTintColor = UIColor.lightGray
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

    @IBAction func presentSafari(sender: AnyObject) {

        let safari = SFSafariViewController(url: URL(string: "https://www.google.com/")!)
        safari.delegate = self
        present(safari, animated: true) {
        }
    }

    // MARK: - SFSafariViewControllerDelegate
    func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
        dismiss(animated: true, completion: nil)
    }
}

Dhaval H. Nena
  • 3,992
  • 1
  • 37
  • 50

2 Answers2

2

Set modalPresentationCapturesStatusBarAppearance to takes over control of status bar appearance from the presenting view controller.

@IBAction func presentSafari(sender: AnyObject) {

    let safari = SFSafariViewController(url: URL(string: "https://www.google.com/")!)
    safari.delegate = self
    safari.modalPresentationCapturesStatusBarAppearance = true
    if #available(iOS 10.0, *) {
        safari.preferredBarTintColor = .yellow
    } else {
        // Fallback on earlier versions
        safari.view.tintColor = .yellow
    }
    present(safari, animated: true) {
    }
}

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

When you present a view controller by calling the present(_:animated:completion:) method, status bar appearance control is transferred from the presenting to the presented view controller only if the presented controller's modalPresentationStyle value is UIModalPresentationStyle.fullScreen. By setting this property to true, you specify the presented view controller controls status bar appearance, even though presented non-fullscreen.

Output: Screenshot

enter image description here

Rocky
  • 2,903
  • 1
  • 22
  • 26
  • Tried setting above property, however no success. thanks – Dhaval H. Nena May 23 '19 at 03:34
  • @DhavalH.Nena - update the answer with code & screenshot, is this work for you? – Rocky May 23 '19 at 06:45
  • Instead of black you can set the navigation bar colour like this : safari.preferredBarTintColor = self.navigationController?.navigationBar.tintColor or safari.view.tintColor = safari.preferredBarTintColor = self.navigationController?.navigationBar.tintColor but this works for me. – BhargavR May 23 '19 at 19:06
  • Hi @Rocky, your answer is working fine with black color, however my app theme color is different and that is not working. While testing it further I found some strange behaviour in terms of using different colors, i.e some colors are working fine while some not. For example native colors like black, magenta are working as expected and status bar color is changing to white, however for other colors like yellow, green are not working and status bar color keeps black always. TO BE CONTINUED.. – Dhaval H. Nena May 27 '19 at 09:04
  • Even from my custom colors one is working while other not. ```Swift static let blue = UIColor(red: 61, green: 140, blue: 255). // WORKING static let blueLight = UIColor(red: 0, green: 177, blue: 240) // NOT WORKING ``` I suspect SFSafariViewController is manging the display of status bar color based on some RGB values, though I'm not sure on it. Let me know your thoughts for the same. And thank you for the help! – Dhaval H. Nena May 27 '19 at 09:07
  • Yes, `lightContent` Light content, for use on dark backgrounds only and `default` Dark content, for use on light backgrounds. – Rocky May 27 '19 at 09:09
  • @Rocky any suggestion to make it lightContent on my custom color? – Dhaval H. Nena May 27 '19 at 09:29
  • NO, as my work :) I just tried it with image also but no luck, Apple managing it by self, because if status bar & navigation bar both color get light then issue in user experience. – Rocky May 27 '19 at 10:18
0

iOS 10.0+

preferredBarTintColor

The color to tint the background of the navigation bar and the toolbar.

Ref: https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/2274394-preferredbartintcolor


Since your View controller-based status bar appearance is set to YES in Info.plist, you will need to apply the color information on preferredBarTintColor, like so:

let safari = SFSafariViewController(url: URL(string: "https://google.com")!)

//This:
safari.preferredBarTintColor = .black

present(safari, animated: true, completion: nil)

And... no need for the following:

extension SFSafariViewController {
    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return .default
    }
}
staticVoidMan
  • 19,275
  • 6
  • 69
  • 98
  • nope, I have minimum iOS deployment target of iOS 9.0 and above solution is not working for it. thanks – Dhaval H. Nena May 23 '19 at 03:34
  • thank you for the answer however can you try with yellow or green color. They're not working, for detailed answer please review my comments in below answer. Appreciate your help! – Dhaval H. Nena May 27 '19 at 09:16
  • @DhavalH.Nena True, I checked `safari.view.tintColor` in iOS 9 simulator & you're right. It does not change the `navigationBar`'s `backgroundColor`, it just changes the `barButtonItem`s tint color. – staticVoidMan May 27 '19 at 11:42
  • @DhavalH.Nena I tried a couple of things, even embedded `safari` in a `navigationController` with customizations but that too has it's own caveats. Finally, it seems to me that there's no elegant way to handle this in iOS 9 and so at this point, I would apply the color on `preferredBarTintColor` for iOS 10+ and leave it default for iOS9-. – staticVoidMan May 27 '19 at 11:46
  • navigation bar color is ok, my concern is changing the status bar color of SFSafariViewController when presented. For black, red color its changing to white for other colors its not. If you have any other solution please share. Thanks :) – Dhaval H. Nena May 27 '19 at 12:55