44
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

WKWebViewでJavaScript(Alert,Confirm,Prompt)の処理

WKWebViewは自分でWKUIDelegateを指定してコードを書かない限り以下のような画面は表示されず、JavaScriptからの要求を無視します。

wkwebview_uidelegate.png

左から、JavaScriptのalert,confirm,promptが実行された時の画面です。

以下WKUIDelegateのみを使うことを目的としたコードを記します。

iOS8であればXcodeで新規作成時にSingle View Applicationテンプレートを作成し、ViewController.mにコピペするだけで動きますのでお試しください。

//
//  ViewController.m
//  MyWKWebView
//
//  Created by FukuyamaShingo on 9/22/14.
//  Copyright (c) 2014 Shingo Fukuyama. All rights reserved.
//

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

@interface ViewController ()
<WKUIDelegate>
@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, strong) UIToolbar *toolbar;
@property (nonatomic, strong) UIBarButtonItem *buttonForAlert;
@property (nonatomic, strong) UIBarButtonItem *buttonForConfirm;
@property (nonatomic, strong) UIBarButtonItem *buttonForPrompt;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];


    /*
     * Setup WKWebView only for WKUIDelegate
     */
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
    _webView.UIDelegate = self;
    NSString *urlString = @"https://www.google.com";
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [_webView loadRequest:request];


    /*
     * Setup Toolbar
     */
    _buttonForAlert = [[UIBarButtonItem alloc] initWithTitle:@"Alert"
                                                       style:UIBarButtonItemStylePlain
                                                      target:self
                                                      action:@selector(showAlert:)];
    _buttonForConfirm = [[UIBarButtonItem alloc] initWithTitle:@"Confirm"
                                                         style:UIBarButtonItemStylePlain
                                                        target:self
                                                        action:@selector(showConfirm:)];
    _buttonForPrompt = [[UIBarButtonItem alloc] initWithTitle:@"Prompt"
                                                        style:UIBarButtonItemStylePlain
                                                       target:self
                                                       action:@selector(showPrompt:)];
    _buttonForAlert.width   = 80.0;
    _buttonForConfirm.width = 80.0;
    _buttonForPrompt.width  = 80.0;
    _toolbar = [[UIToolbar alloc] initWithFrame:CGRectZero];
    UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                            target:nil
                                                                            action:nil];
    _toolbar.items = @[_buttonForAlert, spacer, _buttonForConfirm, spacer, _buttonForPrompt];

    [self.view addSubview:_webView];
    [self.view addSubview:_toolbar];
    [self setupConstraints];
}

- (void)showAlert:(UIBarButtonItem *)sender
{
    NSString *promptCode = @"alert('Alertが押されました');";
    [_webView evaluateJavaScript:promptCode completionHandler:^(id object, NSError *error) { }];
}

- (void)showConfirm:(UIBarButtonItem *)sender
{
    NSString *promptCode = @"var confirmed = confirm('OK?');";
    [_webView evaluateJavaScript:promptCode completionHandler:^(id object, NSError *error) { }];
}

- (void)showPrompt:(UIBarButtonItem *)sender
{
    NSString *promptCode = @"var person = prompt('名前を入力してください', 'デフォルト');";
    [_webView evaluateJavaScript:promptCode completionHandler:^(id object, NSError *error) { }];
}


#pragma mark - WKUIDelegate

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler
{
    NSString *hostString = webView.URL.host;
    NSString *sender = [NSString stringWithFormat:@"%@からの表示", hostString];

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:sender preferredStyle:UIAlertControllerStyleAlert];

    [alertController addAction:[UIAlertAction actionWithTitle:@"閉じる" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        completionHandler();
    }]];
    [self presentViewController:alertController animated:YES completion:^{}];
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler
{
    NSString *hostString = webView.URL.host;
    NSString *sender = [NSString stringWithFormat:@"%@からの表示", hostString];

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:sender preferredStyle:UIAlertControllerStyleAlert];
    [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
        //textField.placeholder = defaultText;
        textField.text = defaultText;
    }];
    [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSString *input = ((UITextField *)alertController.textFields.firstObject).text;
        completionHandler(input);
    }]];
    [alertController addAction:[UIAlertAction actionWithTitle:@"キャンセル" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        completionHandler(nil);
    }]];
    [self presentViewController:alertController animated:YES completion:^{}];
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
{
    NSString *hostString = webView.URL.host;
    NSString *sender = [NSString stringWithFormat:@"%@からの表示", hostString];

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:sender preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        completionHandler(YES);
    }]];
    [alertController addAction:[UIAlertAction actionWithTitle:@"キャンセル" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        completionHandler(NO);
    }]];
    [self presentViewController:alertController animated:YES completion:^{}];
}


#pragma mark - Constraints

- (void)setupConstraints
{
    _webView.translatesAutoresizingMaskIntoConstraints = NO;
    [_webView.superview addConstraints:[NSLayoutConstraint
                                        constraintsWithVisualFormat:@"V:|-20.0-[view]-44.0-|"
                                        options:NSLayoutFormatDirectionLeadingToTrailing
                                        metrics:nil
                                        views:@{@"view":_webView}]];
    [_webView.superview addConstraints:[NSLayoutConstraint
                                        constraintsWithVisualFormat:@"H:|-0-[view]-0-|"
                                        options:NSLayoutFormatDirectionLeadingToTrailing
                                        metrics:nil
                                        views:@{@"view":_webView}]];

    _toolbar.translatesAutoresizingMaskIntoConstraints = NO;
    [_toolbar.superview addConstraints:[NSLayoutConstraint
                                        constraintsWithVisualFormat:@"V:[view]-0-|"
                                        options:NSLayoutFormatDirectionLeadingToTrailing
                                        metrics:nil
                                        views:@{@"view":_toolbar}]];
    [_toolbar.superview addConstraints:[NSLayoutConstraint
                                        constraintsWithVisualFormat:@"H:|-0-[view]-0-|"
                                        options:NSLayoutFormatDirectionLeadingToTrailing
                                        metrics:nil
                                        views:@{@"view":_toolbar}]];
    [_toolbar.superview addConstraint:[NSLayoutConstraint constraintWithItem:_toolbar
                                                               attribute:NSLayoutAttributeHeight
                                                               relatedBy:NSLayoutRelationEqual
                                                                  toItem:nil
                                                               attribute:0
                                                              multiplier:1.0
                                                                constant:44.0]];

}

@end

Alert地獄のサイトを回避するために"このページではこれ以上表示しない"などの対策も必要かと思います。

PR: iOS8向けのブラウザアプリを2つほど公開しますので、よろしくお願い致します。
ブログ: http://fukuyama.co/two-app-before-application

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
44
Help us understand the problem. What are the problem?