没有 WKScriptMessage 的 WKWebView 回调

WKWebView callback without WKScriptMessage

关于在 macOS 上使用 WKWebView 和 objective-c 的信息似乎不多,所以我一直在尝试使用各种 iOS/Swift 示例来说明。问题是我从 JS 到 ObjC 的回调不起作用。即使在 userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 函数处设置的断点也永远不会命中。

显然我在这里漏掉了一步。

我的AppDelegate.m:

#import <WebKit/WebKit.h>
#import "AppDelegate.h"

@interface AppDelegate () <WKScriptMessageHandler>

@property (weak) IBOutlet NSWindow *window;
@end

@implementation AppDelegate

- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"callback");
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    WKWebViewConfiguration *config = [WKWebViewConfiguration alloc];
    [[config userContentController] addScriptMessageHandler:self name: @"log"];
    WKWebView *webview = [[WKWebView alloc] initWithFrame:[[_window contentView] frame] configuration:config];
    NSString *htmlStr = @"<!DOCTYPE html><html><body><button type=\"button\" onclick=\"myFunction()\">Click Me!</button><script     type=\"text/javascript\">function myFunction() { window.webkit.messageHandlers.log.postMessage();}</script></body></html>";
    [[_window contentView] addSubview:webview];
    [webview loadHTMLString:htmlStr baseURL:nil];
} 

原始代码不起作用的原因有两个。首先是因为 WKWebviewConfiguration 需要自己初始化(WKWebView 不会为你初始化它的配置),其次是 postMessage 必须至少有一个参数。

#import <WebKit/WebKit.h>
#import "AppDelegate.h"

@interface AppDelegate () <WKScriptMessageHandler>

@property (weak) IBOutlet NSWindow *window;
@end

@implementation AppDelegate

- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"callback");
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    [[config userContentController] addScriptMessageHandler:self name: @"log"];
    WKWebView *webview = [[WKWebView alloc] initWithFrame:[[_window contentView] frame] configuration:config];
    NSString *htmlStr = @"<!DOCTYPE html><html><body><button type=\"button\" onclick=\"myFunction()\">Click Me!</button><script type=\"text/javascript\">function myFunction() { window.webkit.messageHandlers.log.postMessage(null); }</script></body></html>";
    [[_window contentView] addSubview:webview];
    [webview loadHTMLString:htmlStr baseURL:nil];
} 

这是传递参数的方式

 - (void)userContentController:(WKUserContentController *)userContentController
       didReceiveScriptMessage:(WKScriptMessage *)message {
     if ([message.name isEqualToString:@"log"])
         NSLog(@"%@", message.body);

 }
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    [[config userContentController] addScriptMessageHandler:self name: @"log"];
    WKWebView *webview = [[WKWebView alloc] initWithFrame:[[_window contentView] frame] configuration:config];
    NSString *htmlStr = @"<!DOCTYPE html><html><body><button type=\"button\" onclick=\"myFunction()\">Click Me!</button><script type=\"text/javascript\">function myFunction() { window.webkit.messageHandlers.log.postMessage('clicked'); }</script></body></html>";
    [[_window contentView] addSubview:webview];
    [webview loadHTMLString:htmlStr baseURL:nil];
}