IBM Worklight:Call IOS Nativecode When plugin is Created - javascript

I am trying to integrate iOS Native code to my Worklight application.
I Have created a Cordova plug-in with the below code:
HelloWorldPlugin.h
#import <Foundation/Foundation.h>
#import <Cordova/CDV.h>
#interface HelloWorldPlugin : CDVPlugin
{
UINavigationController *navi;
}
-(void)sayHello:(CDVInvokedUrlCommand*)command;
HelloWorldPlugin.m is
-(void)sayHello:(CDVInvokedUrlCommand *)command
{
NSString *responseString=[NSString stringWithFormat:#"Hello........World %#",
[command.arguments objectAtIndex:0]];
CDVPluginResult *pluginResult=[CDVPluginResult
resultWithStatus:CDVCommandStatus_OK mes sageAsString:responseString];
[self.commandDelegate sendPluginResult:pluginResult
callbackId:command.callbackId];
}
The above code is working. Next, I have created a BarcodeScannerViewController Class. It contains: BarcodeScannerViewController.h, BarcodeScannerViewController.m and BarcodeScannerViewController.xib.
I need to call the BarcodeViewController so that the functionality of barcode should happen.
In above HelloWorldPlugin.m I have modified code as below to move to BarcodeScannerViewController
#implementation HelloWorldPlugin
-(void)sayHello:(CDVInvokedUrlCommand *)command
{
NSString *responseString=[NSString stringWithFormat:#"Hello........World %#",
[command.arguments objectAtIndex:0]];
CDVPluginResult *pluginResult=[CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsString:responseString];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
BarCodeScannerViewController *view=[[BarCodeScannerViewController alloc]init];
navi=[[UINavigationController alloc] initWithRootViewController:view];
}
But i am not able to move and getting log error as
2014-07-11 10:06:23.660 HelloWorld[548:60b] THREAD WARNING:
['HelloWorldPlugin'] took
'214928.292969' ms. Plugin should use a background thread.
2014-07-11 10:06:23.666 HelloWorld[548:4207] void SendDelegateMessage(NSInvocation *):
delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:)
failed
to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode

One of the .zip files you've uploaded (in the comments) is no longer available, so I cannot test it myself, but my suggestion is to implement this with the Send Action feature available in Worklight 6.2.
This way the implementation is very clean and straight forward. The basic premise is:
From the application's JavaScript you will invoke an "action"
This action will basically be to display your View Controller
When you're done, you return from your custom View Controller back to the Worklight-provided View Controller (the web app...)
You can read about Send Action as well as see an example implementation, here:
Sending actions and data objects from JavaScript code to native code
Sending actions and data objects from native code to JavaScript code
Question with example code (JS to native)
Example project (native to JS)

Related

Cordova PayPal Plugin integration iOS issue

I have a mobile app with com.paypal.cordova.mobilesdk v3.5.0
I am getting the following error when creating payment in iOS.
Please also note that the app crashes and closes immediately when not in debug mode.
2018-09-02 20:48:29.853486+0200 MyHurryApp[631:122102] -[NSNull length]: unrecognized selector sent to instance 0x1b69ef878
2018-09-02 20:48:29.856680+0200 MyHurryApp[631:122102] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x1b69ef878'
*** First throw call stack:
(0x1843bad8c 0x1835745ec 0x1843c8098 0x1843c05c8 0x1842a641c 0x102ad75e8 0x1028c1c20 0x1033211dc 0x10332119c 0x103325d2c 0x184363070 0x184360bc8 0x184280da8 0x186266020 0x18e2a0758 0x1028beb90 0x183d11fc0)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
The line causing this crash seems to be:
[PayPalMobile preconnectWithEnvironment:environmentToUse];
```
- (void)prepareToRender:(CDVInvokedUrlCommand *)command {
[self.commandDelegate runInBackground:^{
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
NSString *environment = [command.arguments objectAtIndex:0];
NSString *environmentToUse = [self parseEnvironment:environment];
if (environmentToUse) {
// save configuration
PayPalConfiguration *configuration = [self getPayPalConfigurationFromDictionary:[command.arguments objectAtIndex:1]];
self.configuration = configuration;
// do preconnect
dispatch_async(dispatch_get_main_queue(), ^{
[PayPalMobile preconnectWithEnvironment:environmentToUse];
});
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:#"The provided environment is not supported"];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}];
}
```
In other forums I've seen suggestions that you should convert the payment amount to string, which I did however the issue is still there. Click here for example
Any other suggestions please?
Citing from the plugins readme:
Important: PayPal Mobile SDKs are now Deprecated and only existing integrations are supported. For all new integrations, use Braintree Direct in supported countries. In other countries, use Express Checkout and choose the Braintree SDK integration option.
The same warning is also shown at the paypal developer page.
So I guess your app is crashing at this:
[PayPalMobile preconnectWithEnvironment:environmentToUse];
position because you are trying to connect with a new environment, which is not supported anymore.
Most apps use the in-app-browser for realizing PayPal checkouts now.

UIWebView JavaScript losing reference to iOS JSContext namespace (object)

I've been working on a proof of concept app that leverages two-way communication between Objective C (iOS 7) and JavaScript using the WebKit JavaScriptCore framework. I was finally able to get it working as expected, but have run into a situation where the UIWebView loses its reference to the iOS object that I've created via JSContext.
The app is a bit complex, here are the basics:
I'm running a web server on the iOS device (CocoaHTTPServer)
The UIWebView initially loads a remote URL, and is later redirected back to localhost as part of the app flow (think OAuth)
The HTML page that the app hosts (at localhost) has the JavaScript that should be talking to my iOS code
Here's the iOS side, my ViewController's .h:
#import <UIKit/UIKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
// These methods will be exposed to JS
#protocol DemoJSExports <JSExport>
-(void)jsLog:(NSString*)msg;
#end
#interface Demo : UIViewController <UserInfoJSExports, UIWebViewDelegate>
#property (nonatomic, readwrite, strong) JSContext *js;
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#end
And the pertinent parts of the ViewController's .m:
-(void)viewDidLoad {
[super viewDidLoad];
// Retrieve and initialize our JS context
NSLog(#"Initializing JavaScript context");
self.js = [self.webView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
// Provide an object for JS to access our exported methods by
self.js[#"ios"] = self;
// Additional UIWebView setup done here...
}
// Allow JavaScript to log to the Xcode console
-(void)jsLog(str) {
NSLog(#"JavaScript: %#", str);
}
Here is the (simplified for the sake of this question) HTML/JS side:
<html>
<head>
<title>Demo</title>
<script type="text/javascript">
function setContent(c, noLog){
with(document){
open();
write('<p>' + c + '</p>');
close();
}
// Write content to Xcode console
noLog || ios.jsLog(c);
}
</script>
</head>
<body onload="javascript:setContent('ios is: ' + typeof ios)">
</body>
</html>
Now, in almost all cases this works beautifully, I see ios is: object both in the UIWebView and in Xcode's console. Very cool. But in one particular scenario, 100% of the time, this fails after a certain number of redirects in the UIWebView, and once the above page finally loads it says:
ios is: undefined
...and the rest of the JS logic quits because the subsequent call to ios.jsLog in the setContent function results in an undefined object exception.
So finally my question: what could/can cause a JSContext to be lost? I dug through the "documentation" in the JavaScriptCore's .h files and found that the only way this is supposed to happen is if there are no more strong references to the JSContext, but in my case I have one of my own, so that doesn't seem right.
My only other hypothesis is that it has to do with the way in which I'm acquiring the JSContext reference:
self.js = [self.webView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
I'm aware that this may not be officially supported by Apple, although I did find at least one SO'er that said he had an Apple-approved app that used that very method.
EDIT
I should mention, I implemented UIWebViewDelegate to check the JSContext after each redirect in the UIWebView thusly:
-(void)webViewDidFinishLoad:(UIWebView *)view{
// Write to Xcode console via our JSContent - is it still valid?
[self.js evaluateScript:#"ios.jsLog('Can see JS from obj c');"];
}
This works in all cases, even when my web page finally loads and reports ios is: undefined the above method simultaneously writes Can see JS from obj c to the Xcode console. This would seem to indicate the JSContext is still valid, and that for some reason it's simply no longer visible from JS.
Apologies for the very long-winded question, there is so little documentation on this out there that I figured the more info I could provide, the better.
The page load can cause the WebView (and UIWebView which wraps WebView) to get a new JSContext.
If this was MacOS we were talking about, then as shown in the section on WebView in the 2013 WWDC introduction "Integrating JavaScript into Native Apps" session on Apple's developer network (https://developer.apple.com/videos/wwdc/2013/?id=615), you would need to implement a delegate for the frame load and initialise your JSContext variables in your implementation of the selector for webView:didCreateJavaScriptContext:forFrame:
In the case of IOS, you need to do this in webViewDidFinishLoad:
-(void)webViewDidFinishLoad:(UIWebView *)view{
self.js = [view valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"]; // Undocumented access to UIWebView's JSContext
self.js[#"ios"] = self;
}
The previous JSContext is still available to Objective-C since you've kept a strong reference to it.
check this UIWebView JSContext
The key point is register a javascript object once JSContext changed. I use a runloop observer to check is there any network operation finished, once it finished, I'll get the changed JSContext, and register any object I want to it.
I didn't try if this work for iframe, if u have to register some objects in iframe, try this
NSArray *frames = [_web valueForKeyPath:#"documentView.webView.mainFrame.childFrames"];
[frames enumerateObjectsUsingBlock:^(id frame, NSUInteger idx, BOOL *stop) {
JSContext *context = [frame valueForKeyPath:#"javaScriptContext"];
context[#"Window"][#"prototype"][#"alert"] = ^(NSString *message) {
NSLog(#"%#", message);
};
}];

How Can I Save An Image To An iPhone Photo Gallery Using PhoneGap?

I am creating a PhoneGap app for the iPhone that displays a gallery of images. Some images are included with the project installation, and some are from the web. When a user clicks on an image, I would like them to be able to save the image to an iPhone photo gallery (Photos). Originally, I would have liked the app to let the user set the image as wallpaper, but found that it would be extremely difficult or impossible.
I could only find one solution for saving the image using PhoneGap and Objective C, but the PhoneGap solution contained the class PhoneGapCommand which is deprecated. I tried using PGPlugin, but could not get the code to work.
I am hoping that someone out there might have a current PhoneGap solution that can perform this task, or if anyone could point me in the right direction, I would really appreciate it!
I know this question is old but it took me a day to figure this out since this example is no longer applicable to the new version of Cordova. I am currently using version 2.5.0, so I thought I'd share this so others would not have to go through the pain I did.
To save an image, you'll have to write your own plug-in. Here are the steps:
Open your Cordova XCODE project and edit config.xml. Add an entry for the plugin you'll be creating.
"name" is the JavaScript namespace you'll be using and "value" is the Objective-C class name.
In your XCODE project, locate the "Plugins" group. Right click it and select "New File..." from the context menu. Add a new class file "MySaveImageToAlbum". It should be inherited from CDVPlugin.
Below are the codes for the header and the implementation files:
// MySaveImageToAlbum.h
#import
#interface MySaveImageToAlbum : CDVPlugin
- (void)saveImageToAlbum:(CDVInvokedUrlCommand*)command;
#end
// MySaveImageToAlbum.m
#import "CDVSaveImageToAlbum.h"
#import <UIKit/UIKit.h>
#implementation MySaveImageToAlbum
- (void)saveImageToAlbum:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSURL *url = [NSURL URLWithString:[command.arguments objectAtIndex:0]];
NSData *args = [NSData dataWithContentsOfURL:url];
if (args != nil && [args length] > 0) {
#try
{
UIImage *image = [UIImage imageWithData:args];
NSData *imgdata = UIImagePNGRepresentation(image);
UIImage *image2 = [UIImage imageWithData:imgdata];
UIImageWriteToSavedPhotosAlbum(image2, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:#"success"];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
#catch (NSException *exception) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
// Was there an error?
if (error != NULL)
{
// Show error message...
}
else // No errors
{
// Show message image successfully saved
}
}
#end
Next, you'll need to create a javascript file that calls this native code. Here's the code:
var SaveImageToAlbum =
{
saveImageToAlbum: function(successCallback,errorCallback,args)
{
cordova.exec(successCallback, errorCallback, "SaveImageToAlbum", "saveImageToAlbum", [args]);
}
};
Make a reference to the JavaScript created in no.4 in your index.html. Suppose you have a canvas and you want to save it as an image to the camera roll, you can use its "toDataURL()" function to return a base64 PNG data. You can then call the saveImageToAlbum function and pass this as a parameter like this:
SaveImageToAlbum.saveImageToAlbum(function(e){
navigator.notification.alert("Image has been successfully saved in the Photo Album.", null, "Image saved!");
},
function(e){
navigator.notification.alert("Image could not be saved in the Photo Album.", null, "Save error!");
},
canvas.toDataURL());
That's it!
Hope you enjoy...
Regards,
Antonio C. Logarta III
I figured it out on my own. I was able to use Jesse MacFadyen's ImageHelper.
http://groups.google.com/group/phonegap/browse_thread/thread/ea7ee31887b2f610/fe2c0b127cf51e7a
http://groups.google.com/group/phonegap/tree/browse_frm/thread/8aeefbb9421f1b81/94963d9742b0738f?hide_quotes=no
When I first implemented this, I had all the code right, but I didn't have ImageHelper added as an entry in the PhoneGap.plist plugins section. I also changed the deprecated PhoneGapCommand to PGPlugin.

Can you call a javascript function from native code (not in a callback) using PhoneGap and iOS?

I'm hoping to be able to use PhoneGap for my app. I will have to build a custom protocol/plugin so that I can call Native methods from the Javascript. I know you can call a success function in the Javascript when the native code returns.
What I need to be able to do is call a javascript function from the native code. Basically the app will connect to an OSX companion app over local network and when the OSX app send data to the iOS app it is processed in an Objective C method, I need to be able to send the result into the PhoneGap/javascript and do something with it in the WebView.
Is this possible? I have only been able to find information about calling native from javascript not the other way around.
Thanks,
Thomas
Using the code from Answer below here:
MyPhoneGapPlugin.m
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
NSLog(#"Connected To %#:%i.", host, port);
NSString* jsString = [NSString stringWithFormat:#"alert(connected to: %#);", host];
[theWebView stringByEvaluatingJavaScriptFromString:jsString];
[self readWithTag:2];
}
Giving me the error 'Unknown receiver 'theWebView' did you mean 'UIWebView'?
UPDATE: Found the answer: using the phonegap helper I can write something like this...
[super writeJavascript:#"alert('connected');"];
You can easily call JavaScript from native code with a UIWebView:
[webView stringByEvaluatingJavaScriptFromString:#"myJSFunction()"];
To use the result of a function somewhere as an arg to a JS function:
NSString *stringData = getStringData(); // however you get it
[webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:#"myJSFunction(%#)", stringData]];
Found the PhoneGap helper to accomplish this... Write javascript to the webView using:
[super writeJavascript:#"alert('it works');"];
You should try this,
[webView stringByEvaluatingJavaScriptFromString:#"sendSelectedDate()"];
Will this work for you?
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DisplayWebContent/Tasks/JavaScriptFromObjC.html
Taken from this page:
You can also call JavaScript functions with arguments. Assume that you have written a JavaScript function which looks like this:
function addImage(image, width, height) { ... }
Its purpose is to add an image to a web page. It is called with three arguments: image, the URL of the image; width, the screen width of the image; and height, the screen height of the image. You can call this method one of two ways from Objective-C. The first creates the array of arguments prior to using the WebScriptObject bridge:
id win = [webView windowScriptObject];
NSArray *args = [NSArray arrayWithObjects:
#"sample_graphic.jpg",
[NSNumber numberWithInt:320],
[NSNumber numberWithInt:240],
nil];
[win callWebScriptMethod:#"addImage"
withArguments:args];

Detecting JavaScript errors in a UIWebView [duplicate]

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.

Categories

Resources