How to fix "EXC_BAD_ACCESS" when creating WKPreferences variable in Swift 4
Asked Answered
S

1

9

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.

Scandalize answered 27/12, 2018 at 2:3 Comment(3)
Please provide a backtrace.Nudi
let preferences = WKPreferences() works for me. What happens when you create a new project and use that one line in viewWillAppear()?Nudi
@JeshuaLacock The crash is perfectly reproducible if you just do what the OP said to do.Historicity
H
8

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.

Historicity answered 27/12, 2018 at 2:45 Comment(8)
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?Scandalize
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.Historicity
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!Scandalize
No problem. Extremely well asked question by the way.Historicity
4 years have passed and this is still a bug.Reiko
I was having a similar issue with WKWebViewConfiguration, but my mistake was calling it from a different thread.Hiltan
I'm having the same problem in the latest iOS after WWDC 2024. Shows up on iPhone 15 Pro Max when address sanitizer is disabled, but not in simulator. And not just after startup, but actually anytime I try to set the WKConfiguration .config property or instantiate WKPreferences() in a presented view controller even after viewDidLoad.Applicative
The line let_ = WKPreferences() causes that crash for sure even as the first line of func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {} delegate handler function for SceneDelegate.swiftApplicative

© 2022 - 2024 — McMap. All rights reserved.