Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.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 XCTest:验证弱变量的正确释放_Swift_Xctest_Weak_Capture List - Fatal编程技术网

Swift XCTest:验证弱变量的正确释放

Swift XCTest:验证弱变量的正确释放,swift,xctest,weak,capture-list,Swift,Xctest,Weak,Capture List,最近,我尝试使用单元测试验证我编写的对象是否正确释放。然而,我发现无论我尝试了什么,在测试完成之前对象都不会释放。因此,我将测试简化为一个简单的示例(见下文),该示例试图证明使用弱变量进行对象释放的基础 在我看来,强引用应该在测试方法退出后停止保留对象,而弱引用在下一个运行循环中引用时应该为nil。然而,弱参考永远不会为零,并且两个测试都失败。我是不是误解了什么?下面是完整的单元测试 class Mock { //class type, should behave with reference

最近,我尝试使用单元测试验证我编写的对象是否正确释放。然而,我发现无论我尝试了什么,在测试完成之前对象都不会释放。因此,我将测试简化为一个简单的示例(见下文),该示例试图证明使用弱变量进行对象释放的基础

在我看来,强引用应该在测试方法退出后停止保留对象,而弱引用在下一个运行循环中引用时应该为nil。然而,弱参考永远不会为零,并且两个测试都失败。我是不是误解了什么?下面是完整的单元测试

class Mock { //class type, should behave with reference semantics

    init() { }
}

class DeallocationTests: XCTestCase {   

    func testWeakVarDeallocation() {   

        let strongMock = Mock()

        weak var weakMock: Mock? = strongMock

        let expt = expectation(description: "deallocated")

        DispatchQueue.main.async {

            XCTAssertNil(weakMock)      //This assertion fails

            expt.fulfill()
        }

        waitForExpectations(timeout: 1.0, handler: nil)
    }

    func testCaptureListDeallocation() {   

        let strongMock = Mock()

        let expt = expectation(description: "deallocated")

        DispatchQueue.main.async { [weak weakMock = strongMock] in

            XCTAssertNil(weakMock)      //This assertion also fails

            expt.fulfill()
        }

        waitForExpectations(timeout: 1.0, handler: nil)
    }
}

我认为XCTest可能以某种方式推迟了释放,但即使将测试方法体包装在
autoreleasepool
中也不会导致对象释放。

问题在于您的
TestWeakvardAllocation()调用
dispatchAsync
块时,
函数尚未退出,因此仍保留对
strongMock
的强引用

像这样尝试(允许退出
testWeakVarDeallocation()
),您将看到
weakMock
按预期变成
nil

class weakTestTests: XCTestCase {
    var strongMock: Mock? = Mock()

    func testWeakVarDeallocation() {
        weak var weakMock = strongMock

        print("weakMock is \(weakMock)")

        let expt = self.expectation(description: "deallocated")

        strongMock = nil

        print("weakMock is now \(weakMock)")

        DispatchQueue.main.async {
            XCTAssertNil(weakMock)      // This assertion fails

            print("fulfilling expectation")
            expt.fulfill()
        }

        print("waiting for expectation")
        self.waitForExpectations(timeout: 1.0, handler: nil)
        print("expectation fulfilled")
    }
}

weakMock
需要是可选的,例如
弱变量weakMock:Mock?=strongMock
。如果不能将其设置为
nil
,则无法释放。@par
weakMock
是自动可选的,由编译器强制执行。如果检查
weakMock
的类型,它已经是
Mock?
,没有显式的类型注释。如果显式地将其设置为可选,它会变成nil吗?@par,不幸的是,它不会。为了完整起见,我将向示例中添加类型注释。谢谢,但我认为这是一个同步问题。由于您正在调用
waitforexpections()
,因此调用异步块时,
testWeakVarDeallocation()
函数尚未退出。因此,对
strongMock
的引用仍然保留,因此
weakMock
无法转到
nil
。关于对象为什么不解除分配,您是对的,但您的解决方案无法解决问题。测试在第一个异步块运行之前完成并通过,因为没有等待的期望。完全是第二十二条军规。你说得对,XTest函数不会等待。我已经更新了答案,现在它做了正确的事情。是的,这是可行的,我用autoreleasepool解决了下面的问题,但是你的解决方案基本上是一样的。谢谢你的帮助!事实上是不同的。Swift对象不会像您熟悉的(旧式)Objective-C那样被保留和自动删除。由于范围的原因,只有引用计数。