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.
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
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)
}
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.
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)
}
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: {});
}
Ajoutez une préférence à WKWebview pour activer javascript dans viewDidLoad () comme.
// enable JS
webView.configuration.preferences.javaScriptEnabled = true
Enregistrer WKWebview Délégué de l'interface utilisateur dans viewDidLoad () as
self.webView.uiDelegate = self
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)
}