5

In my code, I have a part that creates a new WKWebView with a specific WKWebViewConfiguration, which in turn has a WKPreferences reference. All of this then gets added to the view of the application.

The problem is that up until this point, my code has been running perfectly, with no problems.

Now, for some bizarre reason, when I launch the application, I get

Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeec686fc0)

on the line when I create a variable for the WKPreferences.

I am working with Xcode 10.1, Swift 4, and I have Alamofire and NetworkReachability pods installed. I have tried just creating the WKWebView without the WKPreferences, but the error just moves on to the WKWebViewConfiguration instead.

func createWebView() {
    let preferences = WKPreferences()   //<-- EXC_BAD_ACCESS
    preferences.javaScriptEnabled = true
    let webConfiguration = WKWebViewConfiguration()
    webConfiguration.preferences = preferences
    webConfiguration.allowsInlineMediaPlayback = true
    webViewVar = WKWebView(frame: self.view.bounds, configuration: webConfiguration)
    webViewVar.uiDelegate = self
    self.view = webViewVar
}

override func loadView() {
    createWebView()
}

The expected behavior is that the app would launch and show a web page, that doesn't change, specified elsewhere in the code. The actual result is that the app crashes with the EXC_BAD_ACCESS error upon startup.

Kaushik Makwana
  • 1,287
  • 2
  • 11
  • 24
MattChris
  • 197
  • 2
  • 15

1 Answers1

6

I'd have to say you've found a bug. For some reason, the runtime isn't letting you create a WKPreferences object this early in the life of the app.

The workaround is that you'll have to postpone creation of the web view until the app is up and running. To do so, delete loadView and implement viewDidLoad instead, and do all the work there, making the web view a subview of the main view rather than trying to make it be the main view.

var webViewVar : WKWebView!
func createWebView() {
    let preferences = WKPreferences()
    preferences.javaScriptEnabled = true
    let webConfiguration = WKWebViewConfiguration()
    webConfiguration.preferences = preferences
    webConfiguration.allowsInlineMediaPlayback = true
    webViewVar = WKWebView(frame: self.view.bounds, configuration: webConfiguration)
    webViewVar.uiDelegate = self
    self.view.addSubview(webViewVar)
    webViewVar.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
override func viewDidLoad() {
    super.viewDidLoad()
    createWebView()
}

It's annoying, and you should file a bug report with Apple, but at least this will keep you going for now.

matt
  • 447,615
  • 74
  • 748
  • 977
  • I'll test it out right now, but I just want to ask: whats the `autoresizingMask` line for? Is it just for resizing the WebView if the device goes between portrait and landscape? – MattChris Dec 27 '18 at 02:57
  • It is in case the main view undergoes _any_ other resizing subsequently. Portrait to landscape is a possibility but there are many other possibilities. Basically you cannot assume that the `bounds` of a view during `viewDidLoad` are the bounds it will have when the view actually appears. – matt Dec 27 '18 at 03:00
  • Ok. Good to know. Also, I tested it out, and it worked perfectly as expected. Thank you so much! I'll go file that bug report now! – MattChris Dec 27 '18 at 03:07
  • No problem. Extremely well asked question by the way. – matt Dec 27 '18 at 03:10