Skip to content

Commit

Permalink
Merge pull request #40 from cybozu/fix-memory-leak
Browse files Browse the repository at this point in the history
Prevent memory leaks
  • Loading branch information
b1ackturtle authored Jan 16, 2025
2 parents e6551b4 + 7e24a3c commit 92018cb
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Sources/WebUI/WebView+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension WebView: View {
@MainActor
private func makeView() -> Remakeable<EnhancedWKWebView> {
let webView = Remakeable<EnhancedWKWebView> {
let wrappedView = EnhancedWKWebView(frame: .zero, configuration: parent.configuration)
let wrappedView = EnhancedWKWebView(frame: .zero, configuration: parent.configuration ?? .init())
parent.applyModifiers(to: wrappedView)
return wrappedView
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/WebUI/WebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand Down
26 changes: 26 additions & 0 deletions Tests/WebUITests/WebViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions Tests/WebUITests/XCTestCase+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import XCTest

extension XCTestCase {
func weaklyScope<T: AnyObject>(
_ instance: @autoclosure () -> T,
perform action: (T) -> ()
) -> T? {
weak var weakValue = {
let value = instance()
action(value)
return value
}()
return weakValue
}
}

0 comments on commit 92018cb

Please sign in to comment.