Skip to content

Commit 92018cb

Browse files
authored
Merge pull request #40 from cybozu/fix-memory-leak
Prevent memory leaks
2 parents e6551b4 + 7e24a3c commit 92018cb

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

Sources/WebUI/WebView+Extension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ extension WebView: View {
2020
@MainActor
2121
private func makeView() -> Remakeable<EnhancedWKWebView> {
2222
let webView = Remakeable<EnhancedWKWebView> {
23-
let wrappedView = EnhancedWKWebView(frame: .zero, configuration: parent.configuration)
23+
let wrappedView = EnhancedWKWebView(frame: .zero, configuration: parent.configuration ?? .init())
2424
parent.applyModifiers(to: wrappedView)
2525
return wrappedView
2626
}

Sources/WebUI/WebView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import WebKit
1313
/// ```
1414
@available(iOS 16.4, macOS 13.3, *)
1515
public struct WebView {
16-
let configuration: WKWebViewConfiguration
16+
weak var configuration: WKWebViewConfiguration?
1717

1818
private let initialRequest: URLRequest?
1919

20-
private var uiDelegate: (any WKUIDelegate)?
21-
private var navigationDelegate: (any WKNavigationDelegate)?
20+
private weak var uiDelegate: (any WKUIDelegate)?
21+
private weak var navigationDelegate: (any WKNavigationDelegate)?
2222
private var isInspectable = false
2323
private var allowsBackForwardNavigationGestures = false
2424
private var allowsLinkPreview = true
@@ -30,7 +30,7 @@ public struct WebView {
3030
/// - request: The initial request specifying the URL to load.
3131
/// - configuration: The configuration for the new web view.
3232
@MainActor
33-
public init(request: URLRequest? = nil, configuration: WKWebViewConfiguration = .init()) {
33+
public init(request: URLRequest? = nil, configuration: WKWebViewConfiguration? = nil) {
3434
self.initialRequest = request
3535
self.configuration = configuration
3636
}

Tests/WebUITests/WebViewTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
import XCTest
33

44
final class WebViewTests: XCTestCase {
5+
@MainActor
6+
func test_configuration_is_weakly_referenced() {
7+
var configuration: WebViewConfigurationMock? = .init()
8+
let sut = WebView(configuration: configuration)
9+
configuration = nil
10+
XCTAssertNil(sut.configuration)
11+
}
12+
513
@MainActor
614
func test_applyModifiers_uiDelegate() {
715
let uiDelegateMock = UIDelegateMock()
@@ -11,6 +19,15 @@ final class WebViewTests: XCTestCase {
1119
XCTAssertTrue(uiDelegateMock === webViewMock.uiDelegate)
1220
}
1321

22+
@MainActor
23+
func test_uiDelegate_is_weakly_referenced() {
24+
var sut = WebView()
25+
let actual = weaklyScope(UIDelegateMock()) {
26+
sut = sut.uiDelegate($0)
27+
}
28+
XCTAssertNil(actual)
29+
}
30+
1431
@MainActor
1532
func test_applyModifiers_navigationDelegate() {
1633
let navigationDelegateMock = NavigationDelegateMock()
@@ -20,6 +37,15 @@ final class WebViewTests: XCTestCase {
2037
XCTAssertTrue(navigationDelegateMock === webViewMock.navigationDelegateProxy.delegate)
2138
}
2239

40+
@MainActor
41+
func test_navigationDelegate_is_weakly_referenced() {
42+
var sut = WebView()
43+
let actual = weaklyScope(NavigationDelegateMock()) {
44+
sut = sut.navigationDelegate($0)
45+
}
46+
XCTAssertNil(actual)
47+
}
48+
2349
@MainActor
2450
func test_applyModifiers_isInspectable() {
2551
let sut = WebView().allowsInspectable(true)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import XCTest
2+
3+
extension XCTestCase {
4+
func weaklyScope<T: AnyObject>(
5+
_ instance: @autoclosure () -> T,
6+
perform action: (T) -> ()
7+
) -> T? {
8+
weak var weakValue = {
9+
let value = instance()
10+
action(value)
11+
return value
12+
}()
13+
return weakValue
14+
}
15+
}

0 commit comments

Comments
 (0)