Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift UINavigationController释放测试失败?_Swift_Unit Testing_Uinavigationcontroller_Deinit - Fatal编程技术网

Swift UINavigationController释放测试失败?

Swift UINavigationController释放测试失败?,swift,unit-testing,uinavigationcontroller,deinit,Swift,Unit Testing,Uinavigationcontroller,Deinit,我有以下单元测试: func testReferences() throws { var strongVC: UIViewController? = UIViewController() var strongNC: UINavigationController? = UINavigationController(rootViewController: strongVC!) weak var weakVC = strongVC wea

我有以下单元测试:

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的释放吗?

我记得,文档中说,弱持有的对象“可以随时释放。”操作部分是“可以”

我猜您的视图控制器和导航控制器是自动释放的。这一术语可以追溯到人工参考计数的时代,但在封面下仍然是相关的。创建对象时保留计数为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
        }
    }
}
该代码将导致对
xctasertnil()
的调用被推迟到下一次通过事件循环时

该代码的问题在于,在执行对
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
}

或者把所有东西都放在一个
自动释放池下{..}
?这将避免异步调度。是的,这可能会起作用,因为这会告诉编译器在调用开始时创建一个自动释放池,并在调用结束时耗尽它。好电话。我将编辑我的答案。是的,我之前尝试过DispatchQueue.main.async,但没有成功,但autoreleasepool似乎可以工作。谢谢