2014-11-12 11 views
34

Mam problem z wyświetleniem WKWebView w systemie iOS 8, aby wyświetlić okno dialogowe alertu wywoływane z Javascript. Po utworzeniu standardowego WKWebView i załadowaniu pliku HTML, mam przycisk na stronie, który tworzy prosty alert z pewnym tekstem. Działa to w UIWebView i Google Chrome/Safari, ale wydaje się nie działać w WKWebView. Każda pomoc jest doceniana.System iOS WKWebView nie wyświetlający okna dialogowego alertu javascript()

Moja konfiguracja wygląda następująco:

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]; 

HTML ma następującą funkcję:

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

i przycisk:

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

Ta konfiguracja działa w UIWebView i regularne przeglądarki, ale nie działa w WKWebView. Czy brakuje mi czegoś w konfiguracji? Czy powinienem używać jednego z delegatów WK do kontrolowania zachowania w oknie dialogowym alertu/potwierdzenia? Dziękuję Ci.

+1

Jestem stoi ten sam problem. Nie mogę też połączyć inspektora safari z moim iPadem, więc nie widzę alertów ani pliku console.log. To sprawia, że ​​rozwój na wkwebview to prawie piekło na ziemi. – ruipacheco

+0

możesz spróbować hostować plik html i wypróbować "http: //" zamiast "file: //", może to być spowodowane tym błędem w wkwebview: http://www.openradar.me/radar?id=5839348817723392 – krisrak

+0

Pliki html są przechowywane lokalnie, więc można uzyskać do nich dostęp w trybie offline. Plik ładuje się bez problemu, jest to tylko okno dialogowe alertu, które nie wyświetla się po naciśnięciu przycisku. – Charlie

Odpowiedz

46

Aby rozwiązać ten problem, potrzebujesz narzędzia WKUIDelegate do przeglądania stron internetowych. Obowiązkiem delegata jest podjęcie decyzji, czy należy wyświetlić ostrzeżenie i w jaki sposób. Trzeba to zaimplementować w celu ostrzeżenia, potwierdzenia i wprowadzenia tekstu (monit).

Oto przykładowy kod bez walidacji funkcji URL strony lub bezpieczeństwa:

- (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:^{}]; 
} 

Więcej w Official Documentation

+0

Wygląda na to, że to był problem. Dziękuję Ci! – Charlie

+3

Jeśli nadal nie otrzymujesz tej delegowanej funkcji, pamiętaj, aby wypróbować pozostałe dwa: 'runJavaScriptConfirmPanelWithMessage' oraz' runJavaScriptTextInputPanelWithPrompt'. Zdarzenie zależy od rodzaju alarmu. –

+4

Istnieje świetny zestaw do implementacji wszystkich trzech metod delegatów tutaj: https://gist.github.com/davbeck/8613f2e74e8fc335c14d –

8

Wystarczy rozwinąć nieco, WKWebView wymaga, aby pokazać powiadomienia, monity, a potwierdza siebie. Aby to zrobić, stając się WKUIDelegate:

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

Następnie przypisać delegata:

web.UIDelegate = self; 

Następnie trzeba rzeczywiście wdrożyć alert, szybka i potwierdzić. Tworzę WKWebViewPanelManager.h/m jako łatwej implementacji, więc oto co robię:

- (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]; 
} 

Oczywiście, to do ciebie, aby odfiltrować złe powiadomienie/Potwierdzenie/natychmiastowych żądań.

11

A oto, że w

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

    let alertController = UIAlertController(title: message, message: nil, 
     preferredStyle: UIAlertControllerStyle.Alert); 

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

    self.presentViewController(alertController, animated: true, completion: {}); 
} 
21

Swift 3 z wszystkich 3 opcjonalnych funkcji realizowane:

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) 
} 
+0

gdzie należy wstawić ten kod? Wstawiam to bezpośrednio do 'klasy ViewController' - to kompiluje, ale mój JS nie jest w stanie wyzwolić' prompt() ' – godblessstrawberry

+0

@godblessstrawberry To powinno być wstawione do twojego WKView uiDelegate (WKUIDelegate), zazwyczaj kontrolera widoku, który implementuje ten protokół. – Lio