Pergunta

I am working on an iOS application (iOS 7)

In which I am executing Javascript on UiWebView multiple times

But many times (randomly)

****I get this crash with error [CFRunLoopTimer release]: message sent to deallocated instance

****and sometimes error like this :**** **webthread multiple thread locks not allowed******

I have made ensured that at a time only one thread performs action on UIWebview

I have tried to execute operation on every thread and queue (background thread, main thread , and different global queues) (but no success)

While profiling the application and reproducing the crash on Instruments (zombie mode) I get this message Instrument crash reproduce message

I have thoroughly checked my javascript (it is 100% correct).

But I still get this error many times.

can anyone tell me how to resolve this issue any solution or any tip for debugging this error. (I have already set NSZombienabled = YES ) but this is also of no help.

Foi útil?

Solução

I have been stuck with this exact same bug for quite a while too.

Just like you did I tried pretty much everything, from NSOperationQueue's addOperationWithBlock: to dispatch_async to performSelectorOnMainThread:withObject:waitUntilDone:... (admittedly shooting in the dark)

Then I figured that I was always calling my js code using [myJsContext evaluateScript:jsString];, and getting the JSContext from the UIWebView using [myWebView valueForKeyPath: @"documentView.webView.mainFrame.javaScriptContext"];.

Instead I tried the older [myWebView stringByEvaluatingJavaScriptFromString:jsString];, and it seems to work now (at least it hasn't crashed in a long time).

So maybe that's a solution, as you're using UIWebViews as well? My understanding is that evaluateScript: is especially useful if you're using a JSContext without a UIWebView.

(This answer might lack actual technical certainties, so please dig in if you know more about JavaScriptCore... But hey, it seems to just work for me!)

Outras dicas

I've figured this crash out, just call a dummy stringByEvaluatingJavaScriptFromString on the UIWebView before invoking a method on the context. I believe the reason this works is the call into javascript is done on the Web Thread and it uses a timer to receive the reply back to the main thread, when calling invoke this timer wasn't created so when the reply comes back from the Web Thread it crashes trying to release a timer that was never created in the first place. By using the proper API stringByEvaluatingJavaScriptFromString in insures the timer is created and then the invokeMethod can make use of the same timer.

JSContext* context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
JSValue* value = context[@"Colors"];

// timer CFRelease crash fix
[webView stringByEvaluatingJavaScriptFromString:nil]; 

[value invokeMethod:@"update" withArguments:@[objectID,modifier]];

I suggest you find all NSTimer in your project and look if the some object release it twice. So you can set breakpoints on each method where is the timer is released and look when some method calls this release.

Second suggestion is: Use profiler for allocation all objects and of course activate NSZombie.

You should only call methods on UIWebView from the main thread. UIWebView is not threadsafe and calling methods from multiple threads is unsafe.

You said "I have made ensured that at a time only one thread performs action on UIWebview": this is not enough, unfortunately. Because: you are not the only one making calls on the web view. There are runloop timers. There is the user touching the webview. And other stuff is going on.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top