diff --git a/Sources/WebUI/WebView+Extension.swift b/Sources/WebUI/WebView+Extension.swift index 73c2c9a..6fae5dc 100644 --- a/Sources/WebUI/WebView+Extension.swift +++ b/Sources/WebUI/WebView+Extension.swift @@ -20,7 +20,7 @@ extension WebView: View { @MainActor private func makeView() -> Remakeable { let webView = Remakeable { - let wrappedView = EnhancedWKWebView(frame: .zero, configuration: parent.configuration) + let wrappedView = EnhancedWKWebView(frame: .zero, configuration: parent.configuration ?? .init()) parent.applyModifiers(to: wrappedView) return wrappedView } diff --git a/Sources/WebUI/WebView.swift b/Sources/WebUI/WebView.swift index 70a4437..3c5ac86 100644 --- a/Sources/WebUI/WebView.swift +++ b/Sources/WebUI/WebView.swift @@ -13,12 +13,12 @@ import WebKit /// ``` @available(iOS 16.4, macOS 13.3, *) public struct WebView { - let configuration: WKWebViewConfiguration + weak var configuration: WKWebViewConfiguration? private let initialRequest: URLRequest? - private var uiDelegate: (any WKUIDelegate)? - private var navigationDelegate: (any WKNavigationDelegate)? + private weak var uiDelegate: (any WKUIDelegate)? + private weak var navigationDelegate: (any WKNavigationDelegate)? private var isInspectable = false private var allowsBackForwardNavigationGestures = false private var allowsLinkPreview = true @@ -30,7 +30,7 @@ public struct WebView { /// - request: The initial request specifying the URL to load. /// - configuration: The configuration for the new web view. @MainActor - public init(request: URLRequest? = nil, configuration: WKWebViewConfiguration = .init()) { + public init(request: URLRequest? = nil, configuration: WKWebViewConfiguration? = nil) { self.initialRequest = request self.configuration = configuration } diff --git a/Tests/WebUITests/WebViewTests.swift b/Tests/WebUITests/WebViewTests.swift index 1e37156..4e55e87 100644 --- a/Tests/WebUITests/WebViewTests.swift +++ b/Tests/WebUITests/WebViewTests.swift @@ -2,6 +2,14 @@ import XCTest final class WebViewTests: XCTestCase { + @MainActor + func test_configuration_is_weakly_referenced() { + var configuration: WebViewConfigurationMock? = .init() + let sut = WebView(configuration: configuration) + configuration = nil + XCTAssertNil(sut.configuration) + } + @MainActor func test_applyModifiers_uiDelegate() { let uiDelegateMock = UIDelegateMock() @@ -11,6 +19,15 @@ final class WebViewTests: XCTestCase { XCTAssertTrue(uiDelegateMock === webViewMock.uiDelegate) } + @MainActor + func test_uiDelegate_is_weakly_referenced() { + var sut = WebView() + let actual = weaklyScope(UIDelegateMock()) { + sut = sut.uiDelegate($0) + } + XCTAssertNil(actual) + } + @MainActor func test_applyModifiers_navigationDelegate() { let navigationDelegateMock = NavigationDelegateMock() @@ -20,6 +37,15 @@ final class WebViewTests: XCTestCase { XCTAssertTrue(navigationDelegateMock === webViewMock.navigationDelegateProxy.delegate) } + @MainActor + func test_navigationDelegate_is_weakly_referenced() { + var sut = WebView() + let actual = weaklyScope(NavigationDelegateMock()) { + sut = sut.navigationDelegate($0) + } + XCTAssertNil(actual) + } + @MainActor func test_applyModifiers_isInspectable() { let sut = WebView().allowsInspectable(true) diff --git a/Tests/WebUITests/XCTestCase+Extension.swift b/Tests/WebUITests/XCTestCase+Extension.swift new file mode 100644 index 0000000..5e34773 --- /dev/null +++ b/Tests/WebUITests/XCTestCase+Extension.swift @@ -0,0 +1,15 @@ +import XCTest + +extension XCTestCase { + func weaklyScope( + _ instance: @autoclosure () -> T, + perform action: (T) -> () + ) -> T? { + weak var weakValue = { + let value = instance() + action(value) + return value + }() + return weakValue + } +}