在 ViewControllers 中使用 iOS 7 中的 JavaScriptCore 从 javascript 触发目标 C 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21626137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 21:20:27  来源:igfitidea点击:

Trigger objective C method from javascript using JavaScriptCore in iOS 7 in ViewControllers

javascriptiosobjective-cios7javascriptcore

提问by user3283486

I am loading a url in the webview which has below HTML and javascript function call. Now I am looking into when user touches submit button in webview it should call any method in viewController. Webview should load url(webview delegate) is one approach but is there any new way to get know when javascript function is called by webview should inform viewcontroller or trigger any method in view controller.

我正在 webview 中加载一个 url,它具有以下 HTML 和 javascript 函数调用。现在我正在研究当用户在 webview 中触摸提交按钮时,它应该调用 viewController 中的任何方法。Webview 应该加载 url(webview delegate) 是一种方法,但是有什么新方法可以知道 webview 调用 javascript 函数时应该通知视图控制器或触发视图控制器中的任何方法。

I am not looking for this solution this we need to

我不是在寻找这个我们需要的解决方案

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

    NSLog(@"passed data from web view : %@",[[request URL] query]);

    if([[[request URL] query] isEqualToString:@"clickedOnLineNo"])
    {
//Do your action here

    }

We have to navigate to a fake URL from your javascript method like,

我们必须从你的 javascript 方法导航到一个虚假的 URL,比如,

window.location = "someLink://yourApp/form_Submitted:param1:param2:param3";  

on a button click or your required action.

单击按钮或您需要的操作。

But is there any new possibility from JavaScriptCore to achieve the same.

但是 JavaScriptCore 是否有任何新的可能性来实现相同的目标。

回答by Mike

The Objective-C interface in the JavascriptCore framework introduced with iOS 7 permits calling Objective-C methods from Javascript. For a great intro to these features, check out the 2013 WWDC introduction "Integrating JavaScript into Native Apps" session on Apple's developer network: https://developer.apple.com/videos/wwdc/2013/?id=615

iOS 7 中引入的 JavascriptCore 框架中的 Objective-C 接口允许从 Javascript 调用 Objective-C 方法。有关这些功能的精彩介绍,请查看 Apple 开发者网络上的 2013 年 WWDC 介绍“将 JavaScript 集成到本机应用程序”会话:https: //developer.apple.com/videos/wwdc/2013/?id=615

It does have a brief section towards the end on WebView (MacOs only not iOS)

它在 WebView 的末尾有一个简短的部分(仅限 MacO,而不是 iOS)

The sample code below shows how to implement what you want for iOS.

下面的示例代码显示了如何为 iOS 实现您想要的。

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,40,320,320)];
    webView.delegate = self;
    [self.view addSubview:webView];
     NSString *pageSource = @"<!DOCTYPE html> <html> <head> </head> <body> <h1>My Mobile App</h1> <p>Please enter the Details</p> <form name=\"feedback\" method=\"post\" action=\"mailto:[email protected]\"> <!-- Form elements will go in here --> </form> <form name=\"inputform\"> <input type=\"button\" onClick=\"submitButton('My Test Parameter')\" value=\"submit\"> </form> </body> </html>";
    [webView loadHTMLString:pageSource baseURL:nil];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    JSContext *context =  [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // Undocumented access
    context[@"submitButton"] = ^(NSString *param1) {
        [self yourObjectiveCMethod:param1];
    };
}

- (void)yourObjectiveCMethod:(NSString *)param1 {
    NSLog(@"User clicked submit. param1=%@", param1);
}

Things to note:

注意事项:

  • Accessing the JSContext of a UIWebView is undocumented. Two techniques are known (see Access the JavaScriptCore engine of a UIWebView). The first technique is used here.
  • You don't need to define the javascript function "submitButton" inside the page, you will define the function from Objective-C using the webView's JSContext
  • A page load in a webview causes its JSContext to get replaced, hence you should implement a delegate for the UIWebView and define your Objective-C callback in your implementation of the selector for -webViewDidFinishLoad:
  • I've assumed you will want to pass parameters to this callback, so I've shown a sample parameter. Although this is not covered in the video tutorial mentioned above (or the PDF equivalent), looking at JSValue.h shows that JavascriptCore offers built-in conversion between the following Objective-C and Javascript types:
  • 访问 UIWebView 的 JSContext 没有记录。已知两种技术(请参阅访问 UIWebView 的 JavaScriptCore 引擎)。这里使用第一种技术。
  • 您不需要在页面内定义 javascript 函数“submitButton”,您将使用 webView 的 JSContext 从 Objective-C 定义该函数
  • webview 中的页面加载会导致其 JSContext 被替换,因此您应该为 UIWebView 实现一个委托,并在 -webViewDidFinishLoad 的选择器的实现中定义您的 Objective-C 回调:
  • 我假设您希望将参数传递给此回调,因此我展示了一个示例参数。尽管上面提到的视频教程(或 PDF 等效文件)中没有涉及到这一点,但查看 JSValue.h 会发现 JavascriptCore 提供了以下 Objective-C 和 Javascript 类型之间的内置转换:

.

.

  Objective-C type  |   JavaScript type
--------------------+---------------------
        nil         |     undefined
       NSNull       |        null
      NSString      |       string
      NSNumber      |   number, boolean
    NSDictionary    |   Object object
      NSArray       |    Array object
       NSDate       |     Date object
      NSBlock *     |   Function object *
         id **      |   Wrapper object **
       Class ***    | Constructor object ***

* Instances of NSBlock with supported arguments types will be presented to
JavaScript as a callable Function object. For more information on supported
argument types see JSExport.h. If a JavaScript Function originating from an
Objective-C block is converted back to an Objective-C object the block will
be returned. All other JavaScript functions will be converted in the same
manner as a JavaScript object of type Object.

** For Objective-C instances that do not derive from the set of types listed
above, a wrapper object to provide a retaining handle to the Objective-C
instance from JavaScript. For more information on these wrapper objects, see
JSExport.h. When a JavaScript wrapper object is converted back to Objective-C
the Objective-C instance being retained by the wrapper is returned.

*** For Objective-C Class objects a constructor object containing exported
class methods will be returned. See JSExport.h for more information on
constructor objects.