测试 CLGeocoder geocodeAddressString 方法地标始终为零

test CLGeocoder geocodeAddressString method placemarks is always nil

代码来自书本,第一个XCTFail()总是失败,我在设备和模拟器上都试过了,应该不是网络问题,查看错误,显示Optional(Error Domain=kCLErrorDomain Code=2 "(null)")

func test_GeocoderWorksAsExpected() {
    let expectation = expectationWithDescription("Wait for geocode")
    CLGeocoder().geocodeAddressString("Infinite Loop 1, Cupertino") {
        (placemarks, error) -> Void in
        let placemark = placemarks?.first

        let coordinate = placemark?.location?.coordinate
        guard let latitude = coordinate?.latitude else {
            XCTFail(); return
        }
        guard let longitude = coordinate?.longitude else {
            XCTFail(); return
        }
        XCTAssertEqualWithAccuracy(latitude, 37.3316851, accuracy: 0.000001)
        XCTAssertEqualWithAccuracy(longitude, -122.0300674, accuracy: 0.000001)

        expectation.fulfill()
    }
    waitForExpectationsWithTimeout(3, handler: nil)
}

您说这不应该是网络错误,但这恰恰是代码为 2 的 CLErrorDomain 错误 (CLError.Network)。您可以出于各种原因得到它。例如,当我尝试监视与 Charles 的通信时得到它,但还没有告诉我的计算机信任 Charles 证书。但是一旦我这样做了,那个错误就消失了。您可能需要确认您没有使用代理服务器或其他会干扰 TLS/HTTPS 请求的网络。

顺便说一句,我还建议:

  • 你应该 defer 实现期望(因此无论你从关闭中采取什么路径,它都会实现);和
  • 您可能想要降低纬度和经度错误检查的准确性(因为我发现我的结果略有不同)。

所以,也许是这样的:

func testGeocoder() {
    let expectation = expectationWithDescription("Wait for geocode")
    CLGeocoder().geocodeAddressString("Infinite Loop 1, Cupertino") { placemarks, error in
        defer { expectation.fulfill() }

        guard error == nil else {
            XCTFail(error!.localizedDescription); return
        }

        guard let coordinate = placemarks?.first?.location?.coordinate else {
            XCTFail("No coordinate"); return
        }

        XCTAssertEqualWithAccuracy(coordinate.latitude, 37.3316851, accuracy: 0.001, "Latitude doesn't match")
        XCTAssertEqualWithAccuracy(coordinate.longitude, -122.0300674, accuracy: 0.001, "Longitude doesn't match")
    }
    waitForExpectationsWithTimeout(3, handler: nil)
}