如何在Cocoa/WebKit应用程序中从Javascript调用Objective-C方法?

13
我有一个使用WebView显示HTML界面的Cocoa应用程序。我该如何从HTML界面内的JavaScript函数调用Objective-C方法?
4个回答

10

谢谢,我在谷歌搜索中不知道怎么错过了这个 :) - georgebrock
2
对于任何寻求iOS帮助的人,请注意上面的答案仅适用于Mac。 - zekel
2
请注意链接已更改,因此仅包含链接的答案现在已不再有用。 - Steven Fisher
5
链接指向“从Objective-C使用JavaScript”,这不是问题所在。此页面展示如何从JavaScript调用obj-C方法:https://developer.apple.com/library/mac/#documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html - auco
1
一个包含大部分使用场景的好样例是:CallJS - https://developer.apple.com/library/mac/samplecode/CallJS/Introduction/Intro.html - PetrV

4

由于苹果的文档对我来说相当晦涩难懂,因此我制作了一个概念验证,用于在Cocoa中从JavaScript调用Objective-C方法以及反之。尽管后者更容易,但考虑到我的经验水平,这仍然很困难。

首先,请确保您的Web视图已设置为setFrameLoadDelegate:

[testWinWebView setFrameLoadDelegate:self];

你需要在网页视图加载完成后告诉它观察特定的对象:
- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowScriptObject forFrame:(WebFrame *)frame {
    //add the controller to the script environment
    //the "ObjCConnector" object will now be available to JavaScript
    [windowScriptObject setValue:self forKey:@"ObjCConnector"];
}

然后是通信业务:

// a few methods to log activity
- (void)acceptJavaScriptFunctionOne:(NSString*) logText {
    NSLog(@"acceptJavaScriptFunctionOne: %@",logText);
}
- (void)acceptJavaScriptFunctionTwo:(NSString*) logText {
    NSLog(@"acceptJavaScriptFunctionTwo: %@",logText);
}

//this returns a nice name for the method in the JavaScript environment
+(NSString*)webScriptNameForSelector:(SEL)sel {
    NSLog(@"%@ received %@ with sel='%@'", self, NSStringFromSelector(_cmd), NSStringFromSelector(sel));
    if(sel == @selector(acceptJavaScriptFunctionOne:))
        return @"functionOne"; // this is what you're sending in from JS to map to above line
    if(sel == @selector(acceptJavaScriptFunctionTwo:))
        return @"functionTwo"; // this is what you're sending in from JS to map to above line
    return nil;
}

//this allows JavaScript to call the -logJavaScriptString: method
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)sel {
    NSLog(@"isSelectorExcludedFromWebScript: %@", NSStringFromSelector(sel));
    if(sel == @selector(acceptJavaScriptFunctionOne:) ||
       sel == @selector(acceptJavaScriptFunctionTwo:))
        return NO;
    return YES;
}

重点在于,如果您有多个希望调用的方法,则需要在isSelectorExcludedFromWebScript方法中将它们全部排除,并且您需要使用javascript调用将其映射到webScriptNameForSelector中的ObjC方法。
完整项目概念证明文件: https://github.com/bytestudios/JS-function-and-ObjC-method-connector

感谢提供有用的信息。这个答案真的帮了我很多!! - Tommy

3
如果你想在iPhone应用程序中实现它,你需要使用UIWebViewDelegate方法shouldStartLoadWithRequest:来进行一些技巧处理:
这个API http://code.google.com/p/jsbridge-to-cocoa/ 可以为您完成。它非常轻量级。

0

我有一个使用NimbleKit的解决方案。它可以从Javascript调用Objective C函数。


4
非常好,你能分享一下吗? - Jonathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接