application crashes trying to communicate between swift code and javascript

I am trying to send message to native(written in swift) and in response of that, calling a javascript function for further process from native using WKWebView. The javascript is written maintaining callbacks so that further process continues. But after 2 callbacks application crashes. Its not giving any clear description of crash.


While debugging, the logs show message : " warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available." and execution continues.

After 2 callbacks between javascript and native it crashes saying BAD_ACCESS

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


xcode 9.2

iOS 11.2.1

Answered by DTS Engineer in 288905022

Where does

NativeBridge
come from? Most
WKWebView
-to-native tech is based on
WKScriptMessage
. Is
NativeBridge
a wrapper around that? Or something else?

btw Your ‘perform selector after delay’ stuff is super scary because it drags you outside of Swift’s type checked environment. I recommend that you use

DispatchQueue.main.asyncAfter(…)
for this sort of thing; it’s based on closures and thus keeps you type safe.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Would you mind showing the part of code where the error occurs ? Otherwise, nearly impossible to analyze your problem through your personal interpretation of it.

//This is the Swift Code which returns data to javascript


// Call this function when you have results to send back to javascript callbacks

// callbackId : int comes from handleCall function

// args: list of objects to send to the javascript callback

func returnResult(callbackId:Int,args:Any...) {

if callbackId==0 {

return

}

var resultArray=[Any]()

if !args.isEmpty {

for arg in args {

var argJSONString:String = ""

if JSONSerialization.isValidJSONObject(arg) {

let data = try! JSONSerialization.data(withJSONObject: arg, options: .prettyPrinted)

argJSONString=String(data:data,encoding:.utf8)!

}



resultArray.append(argJSONString)

}

}


if JSONSerialization.isValidJSONObject(resultArray) {

let data = try! JSONSerialization.data(withJSONObject: resultArray, options: .prettyPrinted)

let resultArrayString:String=String(data:data, encoding:.utf8)!

// We need to perform selector with afterDelay 0 in order to avoid weird recursion stop

// when calling NativeBridge in a recursion more then 200 times :s (fails onto 201th calls!!!)

let javascriptFuncStringLocal:String="NativeBridge.resultForCallback(\(callbackId),\(resultArrayString));"

self.perform(#selector(self.returnResultAfterDelay(javascriptFuncString:)), with: javascriptFuncStringLocal, afterDelay: 1)

}


}


@objc func returnResultAfterDelay(javascriptFuncString:String) {

self.webView.performSelector(onMainThread: #selector(self.webView.evaluateJavaScript(_:completionHandler:)), with: javascriptFuncString, waitUntilDone: false)

}





//Javascript code where response from native is handled

// Automatically called by native layer when a result is available

resultForCallback : function resultForCallback(callbackId, resultArray) {

console.log("In result for call back")

try {

var callback = NativeBridge.callbacks[callbackId];

if (!callback) return;


callback.apply(null,resultArray);

} catch(e) {alert(e)}

}



It retuns data to javascript but abruptly crashes after 2/3 call backs. It doesn't stop on any perticular line of code. It just through an exception in AppDelegate


class AppDelegate: UIResponder, UIApplicationDelegate {

Accepted Answer

Where does

NativeBridge
come from? Most
WKWebView
-to-native tech is based on
WKScriptMessage
. Is
NativeBridge
a wrapper around that? Or something else?

btw Your ‘perform selector after delay’ stuff is super scary because it drags you outside of Swift’s type checked environment. I recommend that you use

DispatchQueue.main.asyncAfter(…)
for this sort of thing; it’s based on closures and thus keeps you type safe.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks a lot. It worked. 😀

DispatchQueue.main.asyncAfter(…) solved my problem. It stopped crashing.

And yes, NativeBridge is a javascript wrapper (message come in and out point for javascript side) which communicate with swift code by posting message using WKScriptMessageHandler only.

application crashes trying to communicate between swift code and javascript
 
 
Q