WKWebView displays white screen on some devices

Hello, I have an app that only contains a WKWebView and loads an URL at startup and that is almost all. It has been working fine for years but for about a month (I guess) some clients reported only whitescreen comes up when the app is opened.

I have no idea what has changed and since it does not happen any of my device I cannot investigate what is wrong.

I've been reported that it shows white screen on iPhone X (iOS 16.5.2) and also on iPhone 14 Pro Max as well. But it is running completely fine most of the devices, including my iPhone 11.

The whole code is like this:


//
//  ViewController.swift
//

import UIKit
import WebKit


class ViewController: UIViewController {
    var webView: WKWebView!
    var request: URLRequest!    
    
   @IBOutlet var webViewContainer: UIView!
   
    override func viewDidLoad() {
        super.viewDidLoad()        

        NSLog("View loading...")
        
        // 1
        let contentController = WKUserContentController();
        contentController.add(
            self,
            name: "route"
        )
        
        // 2
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        
        
        let url = URL(string: "https://www.someurl.com/m/?app=ios")!

        
        let request = URLRequest(url: url)
        
        webViewContainer = UIView()
        

        // 3
        webView = WKWebView(frame: webViewContainer.bounds, configuration: config)
        webView.allowsBackForwardNavigationGestures = false
        webView.translatesAutoresizingMaskIntoConstraints = false
        webViewContainer.addSubview(webView)
        
        webView.leadingAnchor.constraint(equalTo: webViewContainer.leadingAnchor, constant: 0).isActive = true
        webView.trailingAnchor.constraint(equalTo: webViewContainer.trailingAnchor, constant: 0).isActive = true
        webView.topAnchor.constraint(equalTo: webViewContainer.topAnchor, constant: 0).isActive = true
        webView.bottomAnchor.constraint(equalTo: webViewContainer.bottomAnchor, constant: 0).isActive = true
        
        /*
        DispatchQueue.main.async {
            self.webView.load(request)
        }
        */
        webView.load(request)        

        view = webViewContainer
        
        NSLog("View did loaded.")

    }

    @available(iOS 10.0, *)
    func startNavigation(dict: NSDictionary) {
        

        let lat = dict["lat"] as? Double ?? 41.0000
        let lng = dict["lng"] as? Double ?? 28.000
        
        openMaps(latitude: lat, longitude: lng, title: "Hakan Altın")
    }

    @available(iOS 10.0, *)
    func openMaps(latitude: Double, longitude: Double, title: String?) {
        
        let application = UIApplication.shared
        let coordinate = "\(latitude),\(longitude)"
        let encodedTitle = title?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
        let handlers = [
            ("Apple Maps","http://maps.apple.com/?q=\(encodedTitle)&ll=\(coordinate)"),
            ("Google Maps", "comgooglemaps://?q=\(coordinate)"),
            ("Yandex Maps","yandexmaps://build_route_on_map/?lat_to=\(latitude)&lon_to=\(longitude)"),
            ("Waze", "waze://?ll=\(coordinate)"),
            ("Citymapper", "citymapper://directions?endcoord=\(coordinate)&endname=\(encodedTitle)")
        ]
            .compactMap { (name, address) in URL(string: address).map { (name, $0) } }
            .filter { (_, url) in application.canOpenURL(url) }

        NSLog("Navigation apps count:\(handlers.count)")        
        
        guard handlers.count > 1 else {
            if let (_, url) = handlers.first {
                application.open(url, options: [:])
            }
            return
        }
        
        let alert = UIAlertController(title: "Please choose navigation application", message: nil, preferredStyle: .actionSheet)
        handlers.forEach { (name, url) in
            alert.addAction(UIAlertAction(title: name, style: .default) { _ in
                application.open(url, options: [:])
            })
        }
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
    
}        

extension ViewController:WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        NSLog("Command received from browser")
        if message.name == "route", let dict = message.body as? NSDictionary {
            if #available(iOS 10.0, *) {
                startNavigation(dict: dict)
            } else {
                // Fallback on earlier versions
            }
        } else {
            
            NSLog("Unknown browser command?!");
                     
        }
    }
}

//
//  AppDelegate.swift
//
import UIKit

@available(iOS 13.0, *)
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
}


Note: I've also replaced the URL content with only a red-background TEST page in order to eliminate if any javascript error cause the issue but yet clients still get all white blank screen.

Any ideas?





Hi! Any luck with this?

we have same this issue from device like iPhone X (iOS 16.5.2) and also on iPhone 14 Pro Max as well

Any solution - I tested the app on TestFlight. It runs on iPhone 11 Pro Max and iPhone 13 , iPhone XR but not opening on Iphone 14 pro max and its showing white screen

My app has the same issue. I have reproduced it by chance. The webview has called the navigation delegate methods: func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) Then the webview got stuck. Any link failed to load, except links without js. The new webview behaved the same, until I killed and reopen app. I suppose there is an exception in the js code, and the processing in javascriptcore got stuck. I have no idea about how to solve it...

Im having the same issue on my end, and like everyone else this appeared out of nowhere. We haven't updated our app in well over 6 months and this issue just started about a week ago.

  • I have a progress counter in my app for how much of the webview page has loaded (0.1 to 1.0)

After a ton of testing I have found the following.

  • The webview displays properly when it counts up (ex: 0.1, 0.35, 0.653, 1.0)
  • The webview does NOT load properly if the counter is only 0.1 and 1.0 (no in between status)
  • There is no reliable way to test this either, it just randomly decides to do it.
  • I cannot reproduce this problem on an iPad, only iPhones show this error.
WKWebView displays white screen on some devices
 
 
Q