Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed NSInvocation getReturnValue for ARC projects #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 33 additions & 32 deletions EasyJSWebViewProxyDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ - (void) addJavascriptInterfaces:(NSObject*) interface WithName:(NSString*) name
if (! self.javascriptInterfaces){
self.javascriptInterfaces = [[NSMutableDictionary alloc] init];
}

[self.javascriptInterfaces setValue:interface forKey:name];
}

Expand All @@ -101,9 +101,9 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView{
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

NSString *requestString = [[request URL] absoluteString];

if ([requestString hasPrefix:@"easy-js:"]) {
/*
A sample URL structure:
Expand All @@ -112,31 +112,31 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)
*/
NSArray *components = [requestString componentsSeparatedByString:@":"];
//NSLog(@"req: %@", requestString);

NSString* obj = (NSString*)[components objectAtIndex:1];
NSString* method = [(NSString*)[components objectAtIndex:2]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSObject* interface = [javascriptInterfaces objectForKey:obj];

// execute the interfacing method
SEL selector = NSSelectorFromString(method);
NSMethodSignature* sig = [[interface class] instanceMethodSignatureForSelector:selector];
NSInvocation* invoker = [NSInvocation invocationWithMethodSignature:sig];
invoker.selector = selector;
invoker.target = interface;

NSMutableArray* args = [[NSMutableArray alloc] init];

if ([components count] > 3){
NSString *argsAsString = [(NSString*)[components objectAtIndex:3]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSArray* formattedArgs = [argsAsString componentsSeparatedByString:@":"];
for (int i = 0, j = 0, l = [formattedArgs count]; i < l; i+=2, j++){
NSString* type = ((NSString*) [formattedArgs objectAtIndex:i]);
NSString* argStr = ((NSString*) [formattedArgs objectAtIndex:i + 1]);

if ([@"f" isEqualToString:type]){
EasyJSDataFunction* func = [[EasyJSDataFunction alloc] initWithWebView:(EasyJSWebView *)webView];
func.funcID = argStr;
Expand All @@ -150,74 +150,75 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)
}
}
[invoker invoke];

//return the value by using javascript
if ([sig methodReturnLength] > 0){
NSString* retValue;
[invoker getReturnValue:&retValue];

NSString* __unsafe_unretained tempValue;
[invoker getReturnValue:&tempValue];
NSString* retValue = tempValue;

if (retValue == NULL || retValue == nil){
[webView stringByEvaluatingJavaScriptFromString:@"EasyJS.retValue=null;"];
}else{
retValue = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,(CFStringRef) retValue, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
[webView stringByEvaluatingJavaScriptFromString:[@"" stringByAppendingFormat:@"EasyJS.retValue=\"%@\";", retValue]];
}
}

[args release];

return NO;
}

if (! self.realDelegate){
return YES;
}

return [self.realDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}

- (void)webViewDidStartLoad:(UIWebView *)webView{
[self.realDelegate webViewDidStartLoad:webView];

if (! self.javascriptInterfaces){
self.javascriptInterfaces = [[NSMutableDictionary alloc] init];
}

NSMutableString* injection = [[NSMutableString alloc] init];

//inject the javascript interface
for(id key in self.javascriptInterfaces) {
NSObject* interface = [self.javascriptInterfaces objectForKey:key];

[injection appendString:@"EasyJS.inject(\""];
[injection appendString:key];
[injection appendString:@"\", ["];

unsigned int mc = 0;
Class cls = object_getClass(interface);
Method * mlist = class_copyMethodList(cls, &mc);
for (int i = 0; i < mc; i++){
[injection appendString:@"\""];
[injection appendString:[NSString stringWithUTF8String:sel_getName(method_getName(mlist[i]))]];
[injection appendString:@"\""];

if (i != mc - 1){
[injection appendString:@", "];
}
}

free(mlist);

[injection appendString:@"]);"];
}


NSString* js = INJECT_JS;
//inject the basic functions first
[webView stringByEvaluatingJavaScriptFromString:js];
//inject the function interface
[webView stringByEvaluatingJavaScriptFromString:injection];

[injection release];
}

Expand All @@ -226,13 +227,13 @@ - (void)dealloc{
[self.javascriptInterfaces release];
self.javascriptInterfaces = nil;
}

if (self.realDelegate){
[self.realDelegate release];
self.realDelegate = nil;
}

[super dealloc];
}

@end
@end