avatar

Blank SFSafariViewController


Recently We got continuous report from our clients saying they were getting blank In-App browser (SFSafariViewController) instead of the web page it was intended to show. After a little bit of debugging I figured out that It was actually bug from iOS side.

There is even a radar about it which you can find here. Looks like it was intentionally done by Apple. Here is the response from the radar

This is done to ensure SafariViewController can’t be used for loading content offscreen.

In our app, we don’t actually load anything offscreen. There could be some delay to present the SFSafariViewController. These are the possible fix I found on the internet.

  • Make a delay before presenting the view controller
  • Load the view before in hand
  • Make the current window as key window

Adding delay is not user friendly so let’s not look into that. Loading view before in hand works on some cases.

let controller = SFSafariViewController(url: url)
controller.delegate = self // load the view before in hand
present(controller, animated: true, completion: nil)

Other option would be make the current window as key window (only incase if you use multiple windows)

let window = << your current window >>
window.makeKey()
let controller = SFSafariViewController(url: url)
controller.delegate = self
present(controller, animated: true, completion: nil)

What actually works for my case is to present the SFSafariViewController from key window root view controller instead of some view controller in the view hierarchy.

 func openUrl(_ urlString: String, from viewController: UIViewController, completion: (() -> Swift.Void)? = nil) {
    guard let url = URL(string: urlString) else {
        showIncorrectUrlAlert(urlString, from: viewController)
        return
    }

    let vc = SFSafariViewController(url: url)
    vc.delegate = viewController as? SFSafariViewControllerDelegate
    // Present with window root view controller to avoid blank SFSafariViewController
    keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)
}

My guess for this issue or fix would be disconnected view when you push safari view controller that causes window changes.