I would like to use the Springboard services framework to make use of the following code.
SBSLaunchApplicationWithIdentifier(CFSTR("com.apple.preferences"), false);
However when I download the header files and use it in my project it won't build. Please let me know how to make this work.
What exactly are you planning on using that method for? I was under the impression it was for launching an application from a daemon?
There are other ways to launch an application quite easily. The most reliable I have found is to use the display stacks to launch the application properly. Other methods of launching the app tend to cause issues when you close it and attempt to relaunch and it crashes.
Using theos, you could do something like this:
NSMutableArray *displayStacks = nil;
// Display stack names
#define SBWPreActivateDisplayStack [displayStacks objectAtIndex:0]
#define SBWActiveDisplayStack [displayStacks objectAtIndex:1]
#define SBWSuspendingDisplayStack [displayStacks objectAtIndex:2]
#define SBWSuspendedEventOnlyDisplayStack [displayStacks objectAtIndex:3]
// Hook SBDisplayStack to get access to the stacks
%hook SBDisplayStack
-(id)init
{
%log;
if ((self = %orig))
{
NSLog(#"FBAuth: addDisplayStack");
[displayStacks addObject:self];
}
return self;
}
-(void)dealloc
{
[displayStacks removeObject:self];
%orig;
}
%end
And then to launch the app, do this:
id PreferencesApp = [[objc_getClass("SBApplicationController") sharedInstance] applicationWithDisplayIdentifier:#"com.apple.preferences"];
[SBWActiveDisplayStack pushDisplay:PreferencesApp];
However, if you really want to use that method, you need to specify what errors are stopping it from building and check which header files you are using to build it with. You also need to link against the SBS framework.
Related
I am doing VoIP call Application. There i can make call through my application. I have integrated SiriKit setup and added following code.
#pragma mark -Start Audio Call
- (void)resolveContactsForStartAudioCall:(INStartAudioCallIntent *)intent
withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion{
NSLog(#"maytest resolveContactsForStartAudioCall");
NSArray<INPerson *> *recipients = intent.contacts;
NSMutableArray<INPersonResolutionResult *> *resolutionResults = [NSMutableArray array];
if (recipients.count == 0) {
completion(#[[INPersonResolutionResult needsValue]]);
return;
}else if(recipients.count==1){
[resolutionResults addObject:[INPersonResolutionResult successWithResolvedPerson:recipients.firstObject]];
}else if(recipients.count>1){
[resolutionResults addObject:[INPersonResolutionResult disambiguationWithPeopleToDisambiguate:recipients]];
}else{
[resolutionResults addObject:[INPersonResolutionResult unsupported]];
}
completion(resolutionResults);
}
- (void)confirmStartAudioCall:(INStartAudioCallIntent *)intent
completion:(void (^)(INStartAudioCallIntentResponse *response))completion{
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartAudioCallIntent class])];
INStartAudioCallIntentResponse *response = [[INStartAudioCallIntentResponse alloc] initWithCode:INStartAudioCallIntentResponseCodeReady userActivity:userActivity];
completion(response);
}
- (void)handleStartAudioCall:(INStartAudioCallIntent *)intent
completion:(void (^)(INStartAudioCallIntentResponse *response))completion{
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INStartAudioCallIntent class])];
INStartAudioCallIntentResponse *response = [[INStartAudioCallIntentResponse alloc] initWithCode:INStartAudioCallIntentResponseCodeContinueInApp userActivity:userActivity];
completion(response);
}
But, its not making calls through my app. Its making calls through native dialer and some times showing application not yet set up with siri.
Could anyone guide me and after make call, how to save call history.
Thanks!
I encountered this problem too!!!
I my case, it's because I'm calling Siri in Chinese!!!! It takes me a half day to figure it out!!
If I change Siri language to English and everything works just fine!
In Chinese Siri will only call through native dialer no matter how I specify the application.
I'm not sure if it happens on other languages too since I can only test those two.
As far as I can tell the tests in my KIFTestScenario+EXAdditions just go in alphabetical order. How can I get the tests to go in an order that I want. I would rather not simply name them like this scenarioToATestLogin.
Thanks!
We used to have that problem, but now we subclass the KifTestController, and in that controller we add our KifTestScenario's like this:
- (void)initializeScenarios {
[self addScenario:[KIFTestScenario scenarioTestMediaPlayer]];
[self addScenario:[KIFTestScenario scenarioTestVideoPlayer]];
[self addScenario:[KIFTestScenario scenarioTestSharing]];
[self addScenario:[KIFTestScenario scenarioTestContentView]];
}
Then in our AppDelegate, we start up the KiffTest's in this method:
- (void)runIntegrationTests {
[[OurTestController sharedInstance] startTestingWithCompletionBlock:^{
exit([[OurTestController sharedInstance] failureCount]);
}];
}
And our scenarios run in the order that we have added them above.
I've been searching far and long, and to this moment, I did not come across a working solution for PhoneGap / Cordova applications that would show soft keyboard programmatically.
Scenario:
We have a PhoneGap application - a website created in jQuery Mobile - that at one point shows a dialog to the user. This dialog is also a web page and has one single INPUT text box where user should enter a code.
Problem:
When the code dialog is shown, the input box is focused using JavaScript. However, due to restrictions placed on iPhone's internal browser, the soft keyboard does not come up until the user actually really clicks inside the input text box.
What we tried:
creating a hidden text box and making it first responder
making the actual webview a first responder once the input receives focus via JavaScript
using sendActionsForControlEvents to try and delive Touch events to the webview (although if anyone has a working code for a PhoneGap application, I would appreciate if they could share it, since I'm no professional in iOS coding)
Any ideas?
EDIT: The restriction mentioned in this question is for built-in browsers only... if you're aiming Opera, you will be successful by using the following code:
var e = jQuery.Event("keydown", { keyCode: 37 });
$('#element').focus().trigger(e);
EDIT2: This is a final working PhoneGap code that can be used in a plugin:
keyboardhelper.h
//
// keyboardHelper.h
// soft keyboard displaying plugin for PhoneGap
//
// Copyright 2012 Martin Ambrus.
//
#import <Foundation/Foundation.h>
#ifdef CORDOVA_FRAMEWORK
#import <Cordova/CDVPlugin.h>
#else
#import "CDVPlugin.h"
#endif
#interface keyboardHelper : CDVPlugin {
NSString *callbackID;
}
#property (nonatomic, copy) NSString *callbackID;
- (void)showKeyboard:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
#end
keyboardhelper.m
//
// keyboardHelper.m
// soft keyboard displaying plugin for PhoneGap
//
// Copyright 2012 Martin Ambrus.
//
#import "keyboardHelper.h"
#import "AppDelegate.h"
#implementation keyboardHelper
#synthesize callbackID;
-(void)showKeyboard:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
self.callbackID = [arguments pop];
//Get text field coordinate from webview. - You should do this after the webview gets loaded
//myCustomDiv is a div in the html that contains the textField.
int textFieldContainerHeightOutput = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetHeight;"] intValue];
int textFieldContainerWidthOutput = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetWidth;"] intValue];
int textFieldContainerYOffset = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetTop;"] intValue];
int textFieldContainerXOffset = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetLeft;"] intValue];
UITextField *myTextField = [[UITextField alloc] initWithFrame: CGRectMake(textFieldContainerXOffset, textFieldContainerYOffset, textFieldContainerWidthOutput, textFieldContainerHeightOutput)];
[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView addSubview:myTextField];
myTextField.delegate = self;
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: #"ok"];
[self writeJavascript:[pluginResult toSuccessCallbackString:self.callbackID]];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
//here you create your request to the server
return NO;
}
-(BOOL)textFieldDidEndEditing:(UITextField *)textField
{
//here you create your request to the server
return NO;
}
#end
javascript
var keyboardHelper = {
showKeyboard: function(types, success, fail) {
return Cordova.exec(success, fail, "keyboardHelper", "showKeyboard", types);
}
};
You can solve the issue with a config.xml entry these days, add:
<preference name="keyboardDisplayRequiresUserAction" value="false" />
You can get the coordinates for the input field using javascript on the webView. Then, place your own textField right on top of it and in it's delegate method textFieldShouldReturn send a request to the server with the code the user typed in.
//Get text field coordinate from webview. - You should do this after the webview gets loaded
//myCustomDiv is a div in the html that contains the textField.
int textFieldContainerHeightOutput = [[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetHeight;"] intValue];
int textFieldContainerWidthOutput = [[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetWidth;"] intValue];
int textFieldContainerYOffset = [[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetTop;"] intValue];
int textFieldContainerXOffset = [[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"myCustomDiv\").offsetLeft;"] intValue];
myTextField.frame = CGRectMake(textFieldContainerXOffset, textFieldContainerYOffset, textFieldContainerWidthOutput, textFieldContainerHeightOutput);
[webView addSubview:myTextField];
myTextField.delegate = self;
Then you implement textFieldShouldReturn and create your request to the server there.
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
//here you create your request to the server
return NO;
}
This is done in existing project, however without using PhoneGap. I hope you can adapt it to suit your needs.
To remove the text field, you can hide it
myTextField.hidden = YES;
or
myTextField = nil;
or
[myTextField removeFromSuperView];
Prior to iOS 6, Apple only allowed the keyboard to be brought up following a user interaction. In iOS 6 they've introduced the following property for UIWebView which you merely need to set to NO.
"yourWebView".keyboardDisplayRequiresUserAction = NO;
Apple sets this by default to "Yes". Now you can call focus() in your JS and the keyboard will appear.
Have you tried using Native Controls and calling them from Javascript?
Here you have some code that shows the usage of Native Controls on a Phonegap Cordova application (Phonegap 1.5)
https://gist.github.com/1384250
Hope it helps to solve the problem :)
I admit this is private, but it might help you out:
#class UIKeyboard;
void showKeyboard()
{
static UIKeyboard *kb = nil;
if ([[UIKeyboard class] respondsToSelector:#selector(automaticKeyboard)])
kb = [UIKeyboard automaticKeyboard];
else
kb = [UIKeyboard activeKeyboard];
if (kb == nil) {
kb = [[[UIKeyboard alloc] initWithDefaultSize] autorelease];
[[[UIApplication sharedApplication] keyWindow] addSubview:kb];
}
if ([kb respondsToSelector:#selector(orderInWithAnimation:)]) {
[kb orderInWithAnimation:YES];
} else {
[kb activate];
[kb minimize];
[kb maximize];
}
}
And call it like this:
showKeyboard();
I actually just found a solution to this.
Like horak says and as described in this article, with or without soft keyboard, it's now possible to achieve this with iOS 6.0 by using: KeyboardDisplayRequiresUserAction = NO;
As of Cordova 2.2, the iOS property mentioned above can simply be added to the Cordova.plist file:
KeyboardDisplayRequiresUserAction, boolean, NO
This solves it all for everyone using Cordova 2.2. Now just call input.focus() as previously discussed, and the keyboard will automatically appear. For those of us who haven't yet updated our Cordova to the current latest version (2.2), it's fortunately still possible.
Programmatically show keyboard on iPhone using cordova v. < 2.2
Step 1:
Adding property to Cordova.plist
Go to your project > Resources > Cordova.plist. Add: KeyboardDisplayRequiresUserAction, boolean, NO
Step 2:
Adding below code snippet to CDVViewController.m
Search for "#interface CDVViewController" (or similar to locate above file). For Cordova 2.1, go to line 240 (everyone else go to a line after a "IsAtLeastiOSVersion" if statement, sorry can't be more precise than that.) Add this code snippet to your CDVViewController.m on the above mentioned line:
if (IsAtLeastiOSVersion(#"6.0")) {
BOOL keyboardDisplayRequiresUserAction = YES; // KeyboardDisplayRequiresUserAction - defaults to YES
if ([self.settings objectForKey:#"KeyboardDisplayRequiresUserAction"] != nil) {
if ([self.settings objectForKey:#"KeyboardDisplayRequiresUserAction"]) {
keyboardDisplayRequiresUserAction = [(NSNumber*)[self.settings objectForKey:#"KeyboardDisplayRequiresUserAction"] boolValue]; //JB-VAL121212
}
}
// property check for compiling under iOS < 6
if ([self.webView respondsToSelector:#selector(setKeyboardDisplayRequiresUserAction:)]) {
[self.webView setValue:[NSNumber numberWithBool:keyboardDisplayRequiresUserAction] forKey:#"keyboardDisplayRequiresUserAction"];
}
}
Disclaimer: This has been tested on Cordova 2.1 only, it is, however, very likely that it still works with 2.0 or any other earlier version that comes with the CDVViewController.m file)
You can use the FocusOut event on the input field and this will be fired when the Done key is pressed. I could use this on IOS 6 and above. I believe it will also work on previous versions.
I have differences about GHUnit results between run from simulator and run from command line.
How can I use UIApplicationDelegate in cli?
In my sample app - tags stackoverflow-6479906.
I want to transfer apple's OCUnit example to GHUnit one.
Expect:
Both "appDelegate" is not nil.
Current:
Run from simulator works fine. However run from cli raises exception.https://gist.github.com/1046753
Refs: apple's unittest example
Note: I read async NSURLConnection sample, but I do not find solution and adjust in my UIApplicationDelegate case.
I recommend you design your test case for your app delegate such that it instantiates an instance of it and calls methods and tests outputs from there.
Consider a structure such as this:
#interface FizzBuzzObjCStudyTest : GHTestCase {
ObjCStudyAppDelegate *appDelegate;
}
#end
#implementation FizzBuzzObjCStudyTest
-(void)setUp
{
appDelegate = [[ObjCStudyAppDelegate alloc] init];
}
-(void)tearDown
{
[appDelegate release];
}
-(void) testAppDelegate
{
GHAssertNotNil(appDelegate, #"Cannot find the application delegate", nil);
// test other methods of ObjCStudyAppDelegate here, or make more test methods.
}
#end
The GHUnit framework bypasses the UI framework that creates the UIApplicationDelegate in the CLI version. In fact, the GUI version of GHUnit is actually instantiating its own UIApplicationDelegate called GHUnitIPhoneAppDelegate.
Here is a snippet from GHUnitIOSMain.m showing how it sets up its own app delegate for the GUI version:
// If GHUNIT_CLI is set we are using the command line interface and run the tests
// Otherwise load the GUI app
if (getenv("GHUNIT_CLI")) {
retVal = [GHTestRunner run];
} else {
retVal = UIApplicationMain(argc, argv, nil, #"GHUnitIPhoneAppDelegate");
}
I need to have my iPhone Objective-C code catch Javascript errors in a UIWebView. That includes uncaught exceptions, syntax errors when loading files, undefined variable references, etc.
This is for a development environment, so it doesn't need to be SDK-kosher. In fact, it only really needs to work on the simulator.
I've already found used some of the hidden WebKit tricks to e.g. expose Obj-C objects to JS and to intercept alert popups, but this one is still eluding me.
[NOTE: after posting this I did find one way using a debugging delegate. Is there a way with lower overhead, using the error console / web inspector?]
I have now found one way using the script debugger hooks in WebView (note, NOT UIWebView). I first had to subclass UIWebView and add a method like this:
- (void)webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject {
// save these goodies
windowScriptObject = newWindowScriptObject;
privateWebView = webView;
if (scriptDebuggingEnabled) {
[webView setScriptDebugDelegate:[[YourScriptDebugDelegate alloc] init]];
}
}
Next you should create a YourScriptDebugDelegate class that contains methods like these:
// in YourScriptDebugDelegate
- (void)webView:(WebView *)webView didParseSource:(NSString *)source
baseLineNumber:(unsigned)lineNumber
fromURL:(NSURL *)url
sourceId:(int)sid
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: called didParseSource: sid=%d, url=%#", sid, url);
}
// some source failed to parse
- (void)webView:(WebView *)webView failedToParseSource:(NSString *)source
baseLineNumber:(unsigned)lineNumber
fromURL:(NSURL *)url
withError:(NSError *)error
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: called failedToParseSource: url=%# line=%d error=%#\nsource=%#", url, lineNumber, error, source);
}
- (void)webView:(WebView *)webView exceptionWasRaised:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: exception: sid=%d line=%d function=%#, caller=%#, exception=%#",
sid, lineno, [frame functionName], [frame caller], [frame exception]);
}
There is probably a large runtime impact for this, as the debug delegate can also supply methods to be called for entering and exiting a stack frame, and for executing each line of code.
See http://www.koders.com/noncode/fid7DE7ECEB052C3531743728D41A233A951C79E0AE.aspx for the Objective-C++ definition of WebScriptDebugDelegate.
Those other methods:
// just entered a stack frame (i.e. called a function, or started global scope)
- (void)webView:(WebView *)webView didEnterCallFrame:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame;
// about to execute some code
- (void)webView:(WebView *)webView willExecuteStatement:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame;
// about to leave a stack frame (i.e. return from a function)
- (void)webView:(WebView *)webView willLeaveCallFrame:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame;
Note that this is all hidden away in a private framework, so don't try to put this in code you submit to the App Store, and be prepared for some hackery to get it to work.
I created a nice little drop-in category that you can add to your project...
It is based on Robert Sanders solution. Kudos.
You can dowload it here:
UIWebView+Debug
This should make it a lot easier to debug you UIWebView :)
I used the great solution proposed from Robert Sanders: How can my iPhone Objective-C code get notified of Javascript errors in a UIWebView?
That hook for webkit works fine also on iPhone. Instead of standard UIWebView I allocated derived MyUIWebView. I needed also to define hidden classes inside MyWebScriptObjectDelegate.h:
#class WebView;
#class WebFrame;
#class WebScriptCallFrame;
Within the ios sdk 4.1 the function:
- (void)webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject
is deprecated and instead of it I used the function:
- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame
Also, I get some annoying warnings like "NSObject may not respond -windowScriptObject" because the class interface is hidden. I ignore them and it works nice.
One way that works during development if you have Safari v 6+ (I'm uncertain what iOS version you need) is to use the Safari development tools and hook into the UIWebView through it.
In Safari: Enable the Develop Menu (Preferences > Advanced > Show Develop menu in menu bar)
Plug your phone into the computer via the cable.
List item
Load up the app (either through xcode or just launch it) and go to the screen you want to debug.
Back in Safari, open the Develop menu, look for the name of your device in that menu (mine is called iPhone 5), should be right under User Agent.
Select it and you should see a drop down of the web views currently visible in your app.
If you have more than one webview on the screen you can try to tell them apart by rolling over the name of the app in the develop menu. The corresponding UIWebView will turn blue.
Select the name of the app, the develop window opens and you can inspect the console. You can even issue JS commands through it.
Straight Forward Way: Put this code on top of your controller/view that is using the UIWebView
#ifdef DEBUG
#interface DebugWebDelegate : NSObject
#end
#implementation DebugWebDelegate
#class WebView;
#class WebScriptCallFrame;
#class WebFrame;
- (void)webView:(WebView *)webView exceptionWasRaised:(WebScriptCallFrame *)frame
sourceId:(int)sid
line:(int)lineno
forWebFrame:(WebFrame *)webFrame
{
NSLog(#"NSDD: exception: sid=%d line=%d function=%#, caller=%#, exception=%#",
sid, lineno, [frame functionName], [frame caller], [frame exception]);
}
#end
#interface DebugWebView : UIWebView
id windowScriptObject;
id privateWebView;
#end
#implementation DebugWebView
- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame
{
[sender setScriptDebugDelegate:[[DebugWebDelegate alloc] init]];
}
#end
#endif
And then instantiate it like this:
#ifdef DEBUG
myWebview = [[DebugWebView alloc] initWithFrame:frame];
#else
myWebview = [[UIWebView alloc] initWithFrame:frame];
#endif
Using #ifdef DEBUG ensures that it doesn't go in the release build, but I would also recommend commenting it out when you're not using it since it has a performance impact. Credit goes to Robert Sanders and Prcela for the original code
Also if using ARC you may need to add "-fno-objc-arc" to prevent some build errors.
I have created an SDK kosher error reporter that includes:
The error message
The name of the file the error happens in
The line number the error happens on
The JavaScript callstack including parameters passed
It is part of the QuickConnectiPhone framework available from the sourceForge project
There is even an example application that shows how to send an error message to the Xcode terminal.
All you need to do is to surround your JavaScript code, including function definitions, etc. with try catch. It should look like this.
try{
//put your code here
}
catch(err){
logError(err);
}
It doesn't work really well with compilation errors but works with all others. Even anonymous functions.
The development blog is here
is here and includes links to the wiki, sourceForge, the google group, and twitter. Maybe this would help you out.
I have done this in firmware 1.x but not 2.x.
Here is the code I used in 1.x, it should at least help you on your way.
// Dismiss Javascript alerts and telephone confirms
/*- (void)alertSheet:(UIAlertSheet*)sheet buttonClicked:(int)button
{
if (button == 1)
{
[sheet setContext: nil];
}
[sheet dismiss];
}*/
// Javascript errors and logs
- (void) webView: (WebView*)webView addMessageToConsole: (NSDictionary*)dictionary
{
NSLog(#"Javascript log: %#", dictionary);
}
// Javascript alerts
- (void) webView: (WebView*)webView runJavaScriptAlertPanelWithMessage: (NSString*) message initiatedByFrame: (WebFrame*) frame
{
NSLog(#"Javascript Alert: %#", message);
UIAlertSheet *alertSheet = [[UIAlertSheet alloc] init];
[alertSheet setTitle: #"Javascript Alert"];
[alertSheet addButtonWithTitle: #"OK"];
[alertSheet setBodyText:message];
[alertSheet setDelegate: self];
[alertSheet setContext: self];
[alertSheet popupAlertAnimated:YES];
}
See exception handling in iOS7:
http://www.bignerdranch.com/blog/javascriptcore-example/
[context setExceptionHandler:^(JSContext *context, JSValue *value) {
NSLog(#"%#", value);
}];
First setup WebViewJavascriptBridge ,
then override console.error function.
In javascript
window.originConsoleError = console.error;
console.error = (msg) => {
window.originConsoleError(msg);
bridge.callHandler("sendConsoleLogToNative", {
action:action,
message:message
}, null)
};
In Objective-C
[self.bridge registerHandler:#"sendConsoleLogToNative" handler:^(id data, WVJBResponseCallback responseCallback) {
NSString *action = data[#"action"];
NSString *msg = data[#"message"];
if (isStringValid(action)){
if ([#"console.error" isEqualToString:action]){
NSLog(#"JS error :%#",msg);
}
}
}];
A simpler solution for some cases might be to just add Firebug Lite to the Web page.