Skip to content

Instantly share code, notes, and snippets.

@pixelrevision
Last active December 16, 2015 06:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pixelrevision/5392099 to your computer and use it in GitHub Desktop.
Save pixelrevision/5392099 to your computer and use it in GitHub Desktop.
Call native iOS methods in javascript.
<html>
<head>
<script type="text/javascript" src="PXRWebViewMessenger.js"></script>
<script type="text/javascript">
if(document.addEventListener){
document.addEventListener("DOMContentLoaded", onLoaded, false);
}
function onLoaded(){
document.getElementById("testMethodCall1").onclick = function(){
messenger.callMethod("testMethod", {param1: "blam", param2: "booyah"});
}
document.getElementById("testMethodCall2").onclick = function(){
messenger.callMethod("testMethod2");
}
document.getElementById("chainMethods").onclick = function(){
messenger.callMethod("chainMethod1");
messenger.callMethod("chainMethod2");
messenger.callMethod("chainMethod3");
}
document.getElementById("notImplemented").onclick = function(){
messenger.callMethod("notImplemented");
}
}
var messenger = new PXRWebViewMessenger();
</script>
<style type="text/css">
body{
color: #FFFFFF;
background-color: #000000;
padding: 40px;
}
input{
display: block;
}
</style>
</head>
<body>
<input type="button" value="Test Method Call 1" id="testMethodCall1"/>
<input type="button" value="Test Method Call 2" id="testMethodCall2"/>
<input type="button" value="Chain Methods" id="chainMethods"/>
<input type="button" value="Not Implemented" id="notImplemented"/>
</body>
</html>
#import <Foundation/Foundation.h>
@class PXRWebviewMessageHandler;
@protocol PXRWebviewMessageHandlerDelegate <NSObject>
- (void)messageHandler:(PXRWebviewMessageHandler*)mh couldNotApplyMethod:(NSString*)method;
@end
@interface PXRWebviewMessageHandler : NSObject
@property (nonatomic, assign) NSObject <PXRWebviewMessageHandlerDelegate> *delegate;
@property (nonatomic, copy) NSString *prefixTrigger;
- (BOOL)checkRequestForActions:(NSURLRequest*)request;
- (void)processCallback:(NSDictionary*)data;
@end
#import "PXRWebviewMessageHandler.h"
@implementation PXRWebviewMessageHandler
- (id)init{
self = [super init];
self.prefixTrigger = @"pxr";
return self;
}
- (BOOL)checkRequestForActions:(NSURLRequest*)request{
NSString *path = [[request URL] absoluteString];
NSArray *parts = [path componentsSeparatedByString:@"://"];
if(!parts || [parts count] < 1) return false;
if(![[parts objectAtIndex:0] isEqualToString:self.prefixTrigger]){
return NO;
}
NSError *error;
NSString *jsonString = [(NSString*)[parts objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *data = [jsonString dataUsingEncoding:NSASCIIStringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error){
return NO;
}else if(![json objectForKey:@"method"]){
return NO;
}else{
[self processCallback:json];
return YES;
}
return NO;
}
- (void)processCallback:(NSDictionary*)data{
NSString *selectorString;
// lets check to see what type of method we want to call
NSDictionary *params = [data objectForKey:@"params"];
NSString *method = [data objectForKey:@"method"];
if(params){
selectorString = [NSString stringWithFormat:@"%@:", method];
}else{
selectorString = [NSString stringWithFormat:@"%@", method];
}
SEL selector = NSSelectorFromString(selectorString);
if(self.delegate){
if([self.delegate respondsToSelector:selector]){
if(params){
[self.delegate performSelector:selector withObject:params];
return;
}else{
[self.delegate performSelector:selector];
return;
}
}
if([self.delegate respondsToSelector:@selector(messageHandler:couldNotApplyMethod:)]){
[self.delegate messageHandler:self couldNotApplyMethod:method];
}
}
}
@end
var PXRWebViewMessenger = function(){
this.prefixTrigger = "pxr";
this.queue = [];
this.timer = null;
};
PXRWebViewMessenger.prototype.callMethod = function(methodName, params){
var self = this;
var message = {};
message.method = methodName;
message.params = params;
var json = JSON.stringify(message);
var messageOutput = this.prefixTrigger + "://" + json;
this.queue.push(messageOutput);
if(!this.timer){
this.timer = setInterval(function(){
self.processNext();
}, 10);
}
};
PXRWebViewMessenger.prototype.processNext = function(){
var message = this.queue[0];
if(message !== undefined){
console.log("process request " + message);
window.location = message;
}
this.queue.splice(0, 1);
if(this.queue.length === 0){
clearInterval(this.timer);
this.timer = null;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment