This is an automated email from the ASF dual-hosted git repository.
GitToTheHub pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-ios.git
The following commit(s) were added to refs/heads/master by this push:
new ba8b9ecb fix(wkwebview): retain UIDelegate to restore
alert/confirm/prompt (#1686)
ba8b9ecb is described below
commit ba8b9ecb00b62349c5d7be3a83c349292fbcc717
Author: Manuel Beck <[email protected]>
AuthorDate: Fri Aug 7 11:45:43 2026 +0200
fix(wkwebview): retain UIDelegate to restore alert/confirm/prompt (#1686)
- Fixes a regression introduced by #1664 where the property `uiDelegate`
was removed from `CDVWebViewEngine`.
- `WKWebView.UIDelegate` is weak, so the default `CDVWebViewUIDelegate`
could be deallocated after assignment, which breaks JavaScript
alert/confirm/prompt handling. Retain the delegate in `CDVWebViewEngine` by a
strong property `uiDelegate` and clear it during dispose.
- Add a regression test that verifies the web view engine keeps a non-nil
uiDelegate.
- Fixes #1684
* fix: document `uiDelegate`, assign it in `updateWithInfo:`
- The property is not only for retaining the UIDelegate, it's also part of
the exposed CDVWebViewEngine API as readonly, so callers can inspect what
delegate is currently installed. It is also set through `updateWithInfo:`,
which a plugin can call and which is documented in `guides/Setting Delegates,
Preferences and Script Message Handlers in the WebView.md`
* doc: document `uiDelegate` only in header file
Generated-By: GPT-5.3-Codex
---
.../Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.h | 4 ++++
.../Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m | 15 ++++++++++++---
tests/CordovaLibTests/CDVWebViewEngineTests.swift | 11 +++++++++++
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git
a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.h
b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.h
index 95343b82..84b8ce93 100644
--- a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.h
+++ b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.h
@@ -22,6 +22,10 @@
@interface CDVWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol,
WKScriptMessageHandler, WKNavigationDelegate>
+// WKUIDelegate reference for this engine, which can also be set via
`updateWithInfo:`
+// by a plugin. Additionally it is a helper property to retain the UIDelegate,
since
+// WKWebView.UIDelegate is weak and would otherwise be deallocated after
assignment
+// which would cause JavaScript alert/confirm/prompt handling to stop working.
@property (nonatomic, strong, readonly) id <WKUIDelegate> uiDelegate;
- (void)allowsBackForwardNavigationGestures:(CDVInvokedUrlCommand*)command;
diff --git
a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
index 250f2a9b..97f22d2e 100644
--- a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
+++ b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
@@ -43,6 +43,7 @@
@property (nonatomic, readwrite) NSString *CDV_ASSETS_URL;
@property (nonatomic, readwrite) Boolean cdvIsFileScheme;
@property (nullable, nonatomic, strong, readwrite) WKWebViewConfiguration
*configuration;
+@property (nonatomic, strong, readwrite) id <WKUIDelegate> uiDelegate;
@end
@@ -270,7 +271,8 @@
// CDVWebViewUIDelegate instance. This gives library consumers a way to
// override the UI delegate and customize behaviour if needed.
if ([self.viewController conformsToProtocol:@protocol(WKUIDelegate)]) {
- wkWebView.UIDelegate = (id<WKUIDelegate>)self.viewController;
+ self.uiDelegate = (id<WKUIDelegate>)self.viewController;
+ wkWebView.UIDelegate = self.uiDelegate;
} else {
CDVWebViewUIDelegate *uiDelegate = [[CDVWebViewUIDelegate alloc]
initWithViewController:self.viewController];
@@ -278,7 +280,11 @@
uiDelegate.mediaPermissionGrantType = [self
parsePermissionGrantType:[settings
cordovaSettingForKey:@"MediaPermissionGrantType"]];
uiDelegate.allowNewWindows = [settings
cordovaBoolSettingForKey:@"AllowNewWindows" defaultValue:NO];
- wkWebView.UIDelegate = uiDelegate;
+ // Assigning to self.uiDelegate keeps a strong reference to the
delegate,
+ // since WKWebView.UIDelegate is weak and would cause the delegate to
be
+ // deallocated
+ self.uiDelegate = uiDelegate;
+ wkWebView.UIDelegate = self.uiDelegate;
}
if ([self.viewController
conformsToProtocol:@protocol(WKNavigationDelegate)]) {
@@ -301,6 +307,7 @@
{
WKWebView* wkWebView = (WKWebView*)_engineWebView;
[wkWebView.configuration.userContentController
removeScriptMessageHandlerForName:CDV_BRIDGE_NAME];
+ self.uiDelegate = nil;
_engineWebView = nil;
[super dispose];
@@ -427,7 +434,9 @@
}
if (uiDelegate && [uiDelegate conformsToProtocol:@protocol(WKUIDelegate)])
{
- wkWebView.UIDelegate = uiDelegate;
+ // Keep a strong reference to the delegate, since WKWebView.UIDelegate
is weak
+ self.uiDelegate = uiDelegate;
+ wkWebView.UIDelegate = self.uiDelegate;
}
if (settings && [settings isKindOfClass:[CDVSettingsDictionary class]]) {
diff --git a/tests/CordovaLibTests/CDVWebViewEngineTests.swift
b/tests/CordovaLibTests/CDVWebViewEngineTests.swift
index 929acdaf..4a75c28d 100644
--- a/tests/CordovaLibTests/CDVWebViewEngineTests.swift
+++ b/tests/CordovaLibTests/CDVWebViewEngineTests.swift
@@ -38,6 +38,17 @@ class ScriptHandlingViewController: ViewController,
WKScriptMessageHandler {
}
class CDVWebViewEngineTests: XCTestCase {
+ @MainActor func testWebViewUIDelegateIsRetained() {
+ let vc = ViewController()
+ vc.webContentFolderName = "www"
+ vc.startPage = "index.html"
+
+ vc.loadViewIfNeeded()
+
+ let uiDelegate = (vc.webViewEngine as AnyObject).value(forKey:
"uiDelegate")
+ XCTAssertNotNil(uiDelegate)
+ }
+
@MainActor func testViewControllerScriptMessageHandler() {
let vc = ScriptHandlingViewController()
vc.webContentFolderName = "www"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]