There does not seem to be much information out there on using WKWebView with objective-c on macOS so I have been trying to make due using various iOS/Swift examples. The problem is that my callback from JS to ObjC does not work. Even the breakpoint set at the userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message function is never hit.
Clearly I am missing a step here.
My 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];
}
The reason the original code does not work is twofold. First is simply because WKWebviewConfiguration needs to be initialized by itself (WKWebView does not initialize its configuration for you) and second is that postMessage must have at least one argument.
#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];
}
Here is how you would pass an argument
- (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];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With