添加到 UIWindow 后如何销毁 VC?

How to destroy VC after adding to UIWindow?

对于某些类型的测试,我需要将视图控制器放在 UIWindow 中。 UIWindow 本身从不显示。我在销毁视图控制器时遇到问题。

假设我们有

class MyViewController: UIViewController {
    deinit {
        print("MyVC bye-bye")
    }
}

class MyWindow: UIWindow {
    deinit {
        print("MyWindow bye-bye")
    }
}

现在在测试套件中,我可以创建两个对象,它们将被释放。

class MyTests: XCTestCase {
    func test() {
        let vc = MyViewController()
        let window = MyWindow()
    }
}

在控制台输出中,我看到

MyWindow bye-bye
MyVC bye-bye

但是如果我在测试中添加以下行,则两个对象都不会被销毁。

        window.addSubview(vc.view)

window 本身稍后可能会被自动释放池清除。但我主要担心的是视图控制器没有被破坏。

我试过

        vc.view.removeFromSuperview()

但这还不够。

抽取 运行 循环给自动释放池一个刺激,这样在测试结束后没有对象逗留。如果对象是纯本地测试,将对象放在自动释放池中并执行泵:

func test() {
    autoreleasepool {
        let vc = MyViewController()
        let window = MyWindow()
        window.addSubview(vc.view)
    }
    RunLoop.current.run(until: Date())
}

但在大多数测试套件中,视图控制器是测试夹具的一部分。在这种情况下,释放夹具后泵送循环。

override func tearDown() {
    vc = nil
    RunLoop.current.run(until: Date())
    super.tearDown()
}