我有一个问题,我已经想出如何解决,但我想了解为什么它不起作用 - 因为它对我来说毫无意义。这是一个演示我的问题的最小示例:

import XCTest
import CoreLocation

class ExampleTests: XCTestCase {

    var okay: ext!

    // this test works fine
    func testOkay(){
        okay = ext()
        XCTAssertNotNil(okay)
    }

    // this test crashes with EXC_BAD_ACCESS(code=1, address=0x10)
    func testNotOkay(){
        let notOkay: ext
        notOkay = ext()
        XCTAssertNotNil(notOkay)
    }
}

extension ExampleTests {
    class ext : CLPlacemark{

    }
}

我正在按照一本书开发一个简单的 TodoList 应用程序,该应用程序使用 CoreLocation 对地址进行地理编码。作为测试的一部分,我必须创建一个模拟 CLPlacemark 对象来测试地理编码功能。

在书中,我被告知我 将此模拟的变量声明为 Test 类的属性,否则“测试将崩溃,因为在其定义范围之外访问了位置标记”。

这可以在上面的示例中看到。 testOkay() 工作正常,因为 okay 被声明为类属性。 testNotOkay()EXC_BAD_ACCESS 错误而崩溃,因为我试图在函数内实例化 ext 的新实例。

现在,如果我不扩展 CLPlacemark,问题就会消失——即我可以在函数中声明 ext 类型的变量或作为类的属性,没有问题。

这里发生了什么?我看不出为什么第二个例子会在第一个工作时崩溃。在我的实际代码中,当我的模拟地标实例仅用于一两个函数时,将它们声明为类属性似乎很无聊。肯定有一些我不了解 Swift 的原因导致了这个问题。

谢谢!!

最佳答案

我最近在测试需要提供预定义 CLPlacemark 实例作为输入的功能时遇到了这个问题。经过一番研究,我发现有人对 CLBeacon 类有类似的问题。

EXC_BAD_ACCESS when setting a CLBeacon to nil



尽管 Apple 文档说您可以自己创建 CLPlacemark 实例。在子类化方面,这个类不是一个好人。它依赖于一个名为 CLPlacemarkInternal 的私有(private)类,当你创建一个实例时它就是 nil。在下图中,您可以看到此对象在调试器中的外观。 _internal ivar 的值为 0x0 ,即 nil

当您实例化的对象被释放时,会发生 EXC_BAD_ACCESS 消息崩溃。无论您是超出范围还是将另一个对象(或 nil )分配给变量。为什么会发生?这是苹果开发者的问题。但是在下面您可以找到其他人实现的一些解决方法。

  • http://szulctomasz.com/2015/07/01/ios-unit-testing-in-swift-and-clplacemark-mocking.html
  • Extending CLPlacemark results in EXC BAD ACCESS
  • 关于ios - 扩展 CLPlacemark 时的 EXC_BAD_ACCESS -- 在定义范围之外访问的变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41201943/

    10-17 01:47