From 91c5d724136969c62b507d2b24f89dda2deb9f01 Mon Sep 17 00:00:00 2001 From: "Takuto NAKAMURA (Kyome)" Date: Thu, 2 Jan 2025 01:12:13 +0900 Subject: [PATCH 1/2] Fix memory leak issue --- Sources/WebUI/WebViewProxy.swift | 28 ++++++++++++++-------------- Sources/WebUI/WebViewReader.swift | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Sources/WebUI/WebViewProxy.swift b/Sources/WebUI/WebViewProxy.swift index 9148554..00be277 100644 --- a/Sources/WebUI/WebViewProxy.swift +++ b/Sources/WebUI/WebViewProxy.swift @@ -35,6 +35,7 @@ public final class WebViewProxy: ObservableObject { deinit { tasks.forEach { $0.cancel() } + tasks.removeAll() } func setUp(_ webView: Remakeable) { @@ -42,8 +43,7 @@ public final class WebViewProxy: ObservableObject { observe(webView.wrappedValue) webView.onRemake { [weak self] in - guard let self else { return } - observe($0) + self?.observe($0) } } @@ -52,34 +52,34 @@ public final class WebViewProxy: ObservableObject { tasks.removeAll() tasks = [ - Task { @MainActor in + Task { @MainActor [weak self] in for await value in webView.publisher(for: \.title).bufferedValues() { - self.title = value + self?.title = value } }, - Task { @MainActor in + Task { @MainActor [weak self] in for await value in webView.publisher(for: \.url).bufferedValues() { - self.url = value + self?.url = value } }, - Task { @MainActor in + Task { @MainActor [weak self] in for await value in webView.publisher(for: \.isLoading).bufferedValues() { - self.isLoading = value + self?.isLoading = value } }, - Task { @MainActor in + Task { @MainActor [weak self] in for await value in webView.publisher(for: \.estimatedProgress).bufferedValues() { - self.estimatedProgress = value + self?.estimatedProgress = value } }, - Task { @MainActor in + Task { @MainActor [weak self] in for await value in webView.publisher(for: \.canGoBack).bufferedValues() { - self.canGoBack = value + self?.canGoBack = value } }, - Task { @MainActor in + Task { @MainActor [weak self] in for await value in webView.publisher(for: \.canGoForward).bufferedValues() { - self.canGoForward = value + self?.canGoForward = value } } ] diff --git a/Sources/WebUI/WebViewReader.swift b/Sources/WebUI/WebViewReader.swift index 6336eb7..d1940c4 100644 --- a/Sources/WebUI/WebViewReader.swift +++ b/Sources/WebUI/WebViewReader.swift @@ -34,8 +34,8 @@ public struct WebViewReader: View { /// The content and behavior of the view. public var body: some View { content(proxy) - .environment(\.setUpWebViewProxy, SetUpWebViewProxyAction(action: { - proxy.setUp($0) + .environment(\.setUpWebViewProxy, SetUpWebViewProxyAction(action: { [weak proxy] in + proxy?.setUp($0) })) } } From 3a5c52ef86ab7f2e25fe84751b0b3a932985ec6e Mon Sep 17 00:00:00 2001 From: "Takuto NAKAMURA (Kyome)" Date: Fri, 3 Jan 2025 22:21:21 +0900 Subject: [PATCH 2/2] Added WebViewReaderTests --- Tests/WebUITests/WebViewReaderTests.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Tests/WebUITests/WebViewReaderTests.swift diff --git a/Tests/WebUITests/WebViewReaderTests.swift b/Tests/WebUITests/WebViewReaderTests.swift new file mode 100644 index 0000000..57acfac --- /dev/null +++ b/Tests/WebUITests/WebViewReaderTests.swift @@ -0,0 +1,22 @@ +@testable import WebUI +import os +import SwiftUI +import XCTest + +final class WebViewReaderTests: XCTestCase { + @MainActor + func test_WebViewProxy_will_also_be_destroyed_if_WebViewReader_is_destroyed() { + let proxyClient = OSAllocatedUnfairLock(initialState: nil) + let sut = WebViewReader { proxy in + WebView() + .onAppear { + proxyClient.withLock { $0 = proxy } + } + } + UIHostingController(rootView: sut)._render(seconds: 0) + let actual = proxyClient.withLock(\.self) + addTeardownBlock { [weak actual] in + XCTAssertNil(actual) + } + } +}