web-dev-qa-db-fra.com

iOS WKWebView n'affichant pas la boîte de dialogue alerte javascript ()

J'ai des difficultés à obtenir un WKWebView sous iOS 8 pour afficher une boîte de dialogue d'alerte appelée à partir de Javascript. Après avoir créé un WKWebView standard et chargé un fichier HTML, j'ai un bouton sur la page qui crée une alerte simple avec du texte. Cela fonctionne dans UIWebView et dans Google Chrome/Safari, mais ne semble pas fonctionner dans WKWebView. Toute aide est appréciée.

Ma configuration est la suivante:

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.allowsInlineMediaPlayback = YES;
config.mediaPlaybackRequiresUserAction = false;
_wkViewWeb = [[WKWebView alloc] initWithFrame:_viewWeb.frame config];
_wkViewWeb.scrollView.scrollEnabled = NO;
NSString *fullURL = @"file://.../TestSlide.html";
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];

[_wkViewWeb loadRequest:request];

Le html a la fonction suivante:

<SCRIPT Language="JavaScript">
function alertTest() {
    alert("Testing Alerts");
}
</SCRIPT>

Et un bouton:

<b>Test Alerts: <input type="button" value="Alert Popup" onclick="alertTest()"><br></b> <br>

Cette configuration fonctionne dans UIWebView et dans les navigateurs standard, mais pas dans WKWebView. Est-ce que je manque quelque chose dans la configuration? Devrais-je utiliser l'un des délégués WK) pour contrôler le comportement du dialogue alerte/confirmation? Merci.

55
Charlie

Pour résoudre ce problème, vous avez besoin d'un WKUIDelegate pour votre vue Web. Il appartient au délégué de décider si une alerte doit être affichée et de quelle manière. Vous devez l'implémenter pour l'alerte, la confirmation et la saisie de texte (invite).

Voici un exemple de code sans validation de l'URL de la page ou des fonctionnalités de sécurité:

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message
                                                                             message:nil
                                                                      preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"OK"
                                                        style:UIAlertActionStyleCancel
                                                      handler:^(UIAlertAction *action) {
                                                          completionHandler();
                                                      }]];
    [self presentViewController:alertController animated:YES completion:^{}];
}

Plus dans le Documentation officielle

64
Nikola Lajic

Swift avec les 3 fonctions optionnelles implémentées:

func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping () -> Void) {

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler()
    }))

    present(alertController, animated: true, completion: nil)
}


func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping (Bool) -> Void) {

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler(true)
    }))

    alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        completionHandler(false)
    }))

    present(alertController, animated: true, completion: nil)
}


func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt Prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping (String?) -> Void) {

    let alertController = UIAlertController(title: nil, message: Prompt, preferredStyle: .actionSheet)

    alertController.addTextField { (textField) in
        textField.text = defaultText
    }

    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        if let text = alertController.textFields?.first?.text {
            completionHandler(text)
        } else {
            completionHandler(defaultText)
        }
    }))

    alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        completionHandler(nil)
    }))

    present(alertController, animated: true, completion: nil)
}
40
Crashalot

Juste pour développer un peu, WKWebView vous oblige à afficher des alertes, des invites et à vous confirmer. Faites ceci en devenant un WKUIDelegate:

#import <WebKit/WebKit.h>
@interface MyController : UIViewController<WKUIDelegate>

Puis assignez le délégué:

web.UIDelegate = self;

Ensuite, vous devez implémenter alert, Prompt et confirmer. Je crée WKWebViewPanelManager.h/m comme une implémentation facile, alors voici ce que je fais:

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    [WKWebViewPanelManager presentAlertOnController:self.view.window.rootViewController title:@"Alert" message:message handler:completionHandler];
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler {
    [WKWebViewPanelManager presentConfirmOnController:self.view.window.rootViewController title:@"Confirm" message:message handler:completionHandler];
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)Prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler {
    [WKWebViewPanelManager presentPromptOnController:self.view.window.rootViewController title:@"Prompt" message:Prompt defaultText:defaultText handler:completionHandler];
}

Bien entendu, il vous appartient de filtrer les demandes d’alerte/de confirmation/d’invitation erronées.

13
bendytree

Et voici que dans Swift :

func webView(webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String,
             initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {

    let alertController = UIAlertController(title: message,
                                            message: nil,
                                            preferredStyle: .alert)

    alertController.addAction(UIAlertAction(title: "OK", style: .cancel) {
        _ in completionHandler()}
    )

    self.present(alertController, animated: true, completion: nil)
}
12
Stafford Williams

Voici le code en Swift 4.2

func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String,
             initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {

    let alertController = UIAlertController(title: message, message: nil,
                                            preferredStyle: UIAlertController.Style.alert);

    alertController.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.cancel) {
        _ in completionHandler()}
    );

    self.present(alertController, animated: true, completion: {});
}
2
Hassan Taleb
  1. Implémentez le protocole sur votre contrôleur de conteneur WKWebview. WKUIDelegate
  2. Ajoutez une préférence à WKWebview pour activer javascript dans viewDidLoad () comme.

    // enable JS
    webView.configuration.preferences.javaScriptEnabled = true
    
  3. Enregistrer WKWebview Délégué de l'interface utilisateur dans viewDidLoad () as

    self.webView.uiDelegate = self
    
  4. Implémentez le délégué ci-dessous dans votre classe.

    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: 
    String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> 
    Void) {
    let alertController = UIAlertController(title: message,message: nil,preferredStyle: 
    .alert)
    
    alertController.addAction(UIAlertAction(title: "OK", style: .cancel) {_ in 
    completionHandler()})
    
    self.present(alertController, animated: true, completion: nil)
    }
    
0
Muhammad Maqsood