gpt4 book ai didi

ios - UIStoryboardScene 意外地释放其 Controller 而不更改保留计数

转载 作者:行者123 更新时间:2023-11-30 13:30:32 25 4
gpt4 key购买 nike

我正在针对我的 View Controller 运行单元测试。该套件中有两个 View Controller ,其中一个在 Storyboard文件中与另一个 View Controller 有一个segue。

在两个 Controller 的测试中,我以相同的方式创建测试主题:我得到一个带有 storyboardWithName:factory:bundle:storyboard (用于依赖注入(inject)的 Typhoon 使用工厂的事情)。然后,我使用 storyboard.instantiateViewControllerWithIdentifier: 获取 VC。

在我的第一个 View Controller 的测试中,所有测试都通过了。重要的是,仅当 vc 本身超出测试用例的范围,或者新实例成为主题并且旧实例的保留计数减少到 0 时,才会调用 View Controller 的 deinit 方法。

但是,在第二个 VC 的测试中,在这两种情况下,测试都会失败(VC 超出范围或新的 VC 成为主题),因为由于某种原因,对 [ 进行了调用UIStoryboardScene dealloc] 进而调用 Controller 上的 deinit,即使其保留计数仍应为 1(由测试用例保留)。当我将新实例设置为主题时,ARC 向 VC 发送另一条释放消息,并收到 EXC_BAD_ACCESS (CODE=i386, GPFLT)

[UIStoryboardScene dealloc] 发生在 XCTest 框架中的一堆编译代码中(复制到此处),但我相信它发生是因为测试用例正在结束,尽管它不应该结束。

* thread #1: tid = 0x57cf91, 0x00000001089953a3 sbprod`Mode2ViewController.__deallocating_deinit(self=0x00007fd2bbdde5d0) + 19 at Mode2ViewController.swift:68, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
* frame #0: 0x00000001089953a3 sbprod`Mode2ViewController.__deallocating_deinit(self=0x00007fd2bbdde5d0) + 19 at Mode2ViewController.swift:68
frame #1: 0x0000000108995492 sbprod`@objc Mode2ViewController.__deallocating_deinit + 34 at Mode2ViewController.swift:0
frame #2: 0x000000010a1ff702 UIKit`-[UIStoryboardScene dealloc] + 36
frame #3: 0x000000010b04dafe libobjc.A.dylib`objc_object::sidetable_release(bool) + 232
frame #4: 0x000000010b04e0b8 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 488
frame #5: 0x0000000115841f37 XCTest`__24-[XCTestCase invokeTest]_block_invoke_2 + 430
frame #6: 0x0000000115876613 XCTest`-[XCTestContext performInScope:] + 190
frame #7: 0x0000000115841d78 XCTest`-[XCTestCase invokeTest] + 169
frame #8: 0x00000001158423a2 XCTest`-[XCTestCase performTest:] + 459
frame #9: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396
frame #10: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396
frame #11: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396
frame #12: 0x000000011582cb10 XCTest`__25-[XCTestDriver _runSuite]_block_invoke + 51
frame #13: 0x000000011584db4c XCTest`-[XCTestObservationCenter _observeTestExecutionForBlock:] + 640
frame #14: 0x000000011582ca55 XCTest`-[XCTestDriver _runSuite] + 453
frame #15: 0x000000011582d7d1 XCTest`-[XCTestDriver _checkForTestManager] + 259
frame #16: 0x0000000115877a9a XCTest`_XCTestMain + 628

所以:

  1. 为什么要创建 UIStoryboardScene?我不需要场景,只需要 VC 来进行测试。在之前的测试用例中似乎没有发生这种情况。我认为,就 Storyboard而言,两位 VC 之间唯一的区别是,其中一个有一个连续的内容,而另一个则有一个连续的内容。

  2. 如果 UIStoryboardScene 实际上在这两种情况下都存在,为什么它会在应该这样做之前deinit我的 VC?

  3. 我的测试用例在范围上也没有太大不同,但是这个测试用例将一些闭包传递到了一些地方,并且我并不是 100% 知道闭包如何影响 ARC。

<小时/>

编辑:此处显示相关代码。

在我的测试用例中,这是使用 Quick 制作的:

override func spec() {

var subject: Mode2ViewController!

let presentDisplayString = "DesiredString"

describe("Mode2ViewController") {
describe("loading") {
describe("date and location") {
context("when location is available") {
beforeEach {
let system = MockSystemComponents.CreateWith(location: true, groups: nil)

let assembly = ApplicationAssembly().activateWithCollaboratingAssemblies([
system
])

//crash occurs on next line, before the 2nd test case, because the
//old subject has already been deallocated (by UIStoryboardScene)
//but reassigning this var, which had retains it, triggers a release

subject = assembly.mode2ViewController() as! Mode2ViewController
let _ = subject.view
}

it("records the location") {
expect(subject).notTo(beNil())
}

it("displays the location as a meaningful string") {
expect(subject.locationLabel.text).to(equal(presentDisplayString))
}
}
}
}
}
}

注意:上面给出的堆栈跟踪(第一次编辑)来 self 在 Mode2ViewController.deinit() 中插入的断点。

最佳答案

事实证明,问题在于 Objective C 对待以关键字 new 开头的事物的保留计数有所不同。因此,Typhoon 无法处理以 new 开头的方法(请参阅 issue)。

解决方案:重命名我的typhoon方法,并且生成的对象具有正确的保留计数。

关于ios - UIStoryboardScene 意外地释放其 Controller 而不更改保留计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36612081/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com