Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak when adding my app as Host Application #362

Open
adirburke opened this issue Jan 7, 2025 · 1 comment
Open

Memory leak when adding my app as Host Application #362

adirburke opened this issue Jan 7, 2025 · 1 comment

Comments

@adirburke
Copy link

adirburke commented Jan 7, 2025

I am getting a memory leak as soon as I add my app as a Host Application, even if the test is now using the code form the App

//  Created by Adir Burke on 7/1/2025.
//

import XCTest
import ViewInspector
import SwiftUI
import Combine


public protocol TestProtocol {}
public final class TestSpy : TestProtocol {
    public init() {}
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, *)
struct TestView2: View {
    let value : TestProtocol
    
    @State private(set) var flag: Bool
    let publisher = PassthroughSubject<Bool, Never>()
    let inspection = Inspection<Self>()
    var didAppear: ((Self) -> Void)?
    
    var body: some View {
        Button(action: {
            self.flag.toggle()
        }, label: { Text(flag ? "true" : "false") })
        .onReceive(publisher) { self.flag = $0 }
        .onReceive(inspection.notice) { self.inspection.visit(self, $0) }
        .onAppear { self.didAppear?(self) }
    }
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, *)
final class Inspection<V>: InspectionEmissary {
    let notice = PassthroughSubject<UInt, Never>()
    var callbacks = [UInt: (V) -> Void]()
    
    func visit(_ view: V, _ line: UInt) {
        if let callback = callbacks.removeValue(forKey: line) {
            callback(view)
        } else {
            assertionFailure()
        }
    }
}

extension XCTestCase {
    func trackForMemoryLeaks(_ instance: AnyObject, file: StaticString = #filePath, line: UInt = #line) {
        addTeardownBlock { [weak instance] in
            XCTAssertNil(instance, "Instance should have been deallocated. Potential memory leak.", file: file, line: line)
        }
    }
}

final class TestingSomething: XCTestCase {

    @MainActor
    func testMemoryLeak() async throws {
        let spy = TestSpy()
        trackForMemoryLeaks(spy)
        let sut = TestView2(value: spy, flag: false)
        try await  ViewHosting.host(sut) {
            try await sut.inspection.inspect { view in
                let text = try view.implicitAnyView().button().labelView().text().string()
                XCTAssertEqual(text, "false")
                sut.publisher.send(true)
            }
            try await sut.inspection.inspect { view in
                let text = try view.implicitAnyView().button().labelView().text().string()
                XCTAssertEqual(text, "true")
            }
        }

    }

}

Screenshot 2025-01-07 at 9 29 02 pm

The Host Application is set and I get the memory leak, if I remove it I dont get it
Screenshot 2025-01-07 at 9 30 14 pm

@adirburke
Copy link
Author

If I comment out the inspection.inspect code it also doesnt leak

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant