swift - UINavigationController 释放测试失败?

标签 swift unit-testing uinavigationcontroller deinit

我有以下单元测试:

func testReferences() throws {
        var strongVC: UIViewController? = UIViewController()
        var strongNC: UINavigationController? = UINavigationController(rootViewController: strongVC!)
        weak var weakVC = strongVC
        weak var weakNC = strongNC
        strongVC = nil
        
        XCTAssertNotNil(weakVC)
        XCTAssertNotNil(weakNC)
        
        strongNC = nil
        
        XCTAssertNil(weakVC) // fails
        XCTAssertNil(weakNC) // fails
    }

最后两个断言失败。有什么方法可以可靠地测试 UIViewController 和 UINavigationController 的释放?

最佳答案

我记得,文档说弱持有的对象“可能随时被释放”。执行部分是“可能是”。

我猜测您的 View Controller 和导航 Controller 是自动释放的。这个术语可以追溯到手动引用计数时代,但在幕后仍然相关。该对象创建时保留计数为 1,然后添加到“自动释放池”中。然后,下次应用程序的当前函数返回并访问事件循环时,“自动释放池将被耗尽”,这意味着自动释放池中的每个条目都会收到一条释放消息,并将其保留计数减 1。保留计数降至零,对象被释放。

(ARC实际上在幕后使用引用计数,因此保留计数和自动释放池仍然相关。只是使用ARC,编译器会为您维护它们。您的强引用和弱引用会变成调用低级系统保留、释放和自动释放函数。)

我不确定它在测试环境中是否有效,但您也许可以使用如下代码:

func testReferences() throws {
        var strongVC: UIViewController? = UIViewController()
        var strongNC: UINavigationController? = UINavigationController(rootViewController: strongVC!)
        weak var weakVC = strongVC
        weak var weakNC = strongNC
        strongVC = nil
        
        XCTAssertNotNil(weakVC)
        XCTAssertNotNil(weakNC)
        
        strongNC = nil
        DispatchQueue.main.async {
            XCTAssertNil(weakVC) // fails
            XCTAssertNil(weakNC) // fails
        }
    }
}

该代码将导致对 XCTAssertNil() 的调用被推迟,直到下一次通过事件循环。

该代码的问题在于,当执行对 DispatchQueue.main.async() 的调用时,测试可能已经结束。

编辑:

正如 Cristik 在评论中指出的,更好的方法是使用 autoreleasepool 命令:

func testReferences() throws {
    //Define the vars we want to test outside of the auto-release pool statement.
    weak var weakVC: UIViewController
    weak var weakNC: UINavigationController
    autoreleasepool {
        var strongVC: UIViewController? = UIViewController()
        var strongNC: UINavigationController? = UINavigationController(rootViewController: strongVC!)
        weakVC = strongVC
        weakNC = strongNC
        strongVC = nil
        
        XCTAssertNotNil(weakVC)
        XCTAssertNotNil(weakNC)
        
        strongNC = nil
    }
    //Test for nil outside of the autorelasepool statement, 
    //after the auto-release pool is drained.
    XCTAssertNil(weakVC) // fails
    XCTAssertNil(weakNC) // fails
}

关于swift - UINavigationController 释放测试失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64432005/

相关文章:

java - 无法从 intellij idea 运行 junit-5 测试用例

IOS - 在 View Controller 中禁用 View 缓存

ios - MKMapView 看起来偏黄,如何改变颜色?

arrays - Swift - 连接循环数组

c# - 使用 MSTest 属性

ios - 一个 ViewController 可以包含多个父(即包含) Controller 吗?

iphone - 将按钮添加到底部工具栏

arrays - 追加后数组为零

swift - 如何在 Swift 3 中编写 CoreMidi MIDISendSysex 请求?

unit-testing - 如何在grails 2.2.4中模拟 Controller 中的私有(private)方法