IOS WKWebView, не отображающий диалог javascript alert()
У меня возникли проблемы с получением WKWebView в iOS 8 для отображения диалогового окна предупреждения, которое вызывается из Javascript. После создания стандартного WKWebView и загрузки HTML файла у меня есть кнопка на странице, которая создает простое предупреждение с некоторым текстом. Это работает в UIWebView и в Google Chrome/Safari, но, похоже, не работает в WKWebView. Любая помощь приветствуется.
Моя настройка выглядит следующим образом:
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 имеет следующую функцию:
<SCRIPT Language="JavaScript">
function alertTest() {
alert("Testing Alerts");
}
</SCRIPT>
И кнопка:
<b>Test Alerts: <input type="button" value="Alert Popup" onclick="alertTest()"><br></b> <br>
Эта настройка работает в UIWebView и в обычных браузерах, но не работает в WKWebView. Я что-то упустил в конфигурации? Должен ли я использовать одного из делегатов WK для управления диалогом поведения оповещения/подтверждения? Спасибо.
Ответы
Ответ 1
Чтобы решить эту проблему, вам понадобится WKUIDelegate для вашего веб-представления. Делегат обязан решить, следует ли показывать предупреждение, и каким образом. Вам необходимо реализовать это для предупреждения, подтверждения и ввода текста (подсказка).
Вот пример кода без какой-либо проверки URL-адресов страницы или функций безопасности:
- (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:^{}];
}
Подробнее в Официальная документация
Ответ 2
Swift 3 со всеми 3 реализованными дополнительными функциями:
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)
}
Ответ 3
Чтобы немного развернуть, WKWebView
требует, чтобы вы показывали предупреждения, подсказки и подтверждали себя. Сделайте это, став WKUIDelegate
:
#import <WebKit/WebKit.h>
@interface MyController : UIViewController<WKUIDelegate>
Затем назначьте делегат:
web.UIDelegate = self;
Затем вам нужно фактически выполнить предупреждение, приглашение и подтвердить. Я создаю WKWebViewPanelManager.h/m как легкую реализацию, поэтому вот что я делаю:
- (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];
}
Конечно, это зависит от вас, чтобы отфильтровать сообщения о неправильном оповещении/подтверждении/приглашении.
Ответ 4
И вот что в 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)
}
Ответ 5
Вот код в 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: {});
}
Ответ 6
- Реализуйте протокол на вашем контроллере контейнера WKWebview. WKUIDelegate
Добавьте предпочтение WKWebview, чтобы включить JavaScript в viewDidLoad() as.
// enable JS
webView.configuration.preferences.javaScriptEnabled = true
Зарегистрируйте WKWebview делегата пользовательского интерфейса в viewDidLoad() как
self.webView.uiDelegate = self
Реализуйте приведенный ниже делегат в своем классе.
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)
}