除了在其他答案中详尽介绍的信号量技术之外,我们现在可以使用 Xcode 6 中的 XCTest 通过XCTestExpectation
. 这消除了在测试异步代码时对信号量的需求。例如:
- (void)testDataTask
{
XCTestExpectation *expectation = [self expectationWithDescription:@"asynchronous request"];
NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
NSURLSessionTask *task = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
XCTAssertNil(error, @"dataTaskWithURL error %@", error);
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *) response statusCode];
XCTAssertEqual(statusCode, 200, @"status code was not 200; was %d", statusCode);
}
XCTAssert(data, @"data nil");
// do additional tests on the contents of the `data` object here, if you want
// when all done, Fulfill the expectation
[expectation fulfill];
}];
[task resume];
[self waitForExpectationsWithTimeout:10.0 handler:nil];
}
为了未来的读者,虽然调度信号量技术在绝对需要时是一种极好的技术,但我必须承认,我看到太多不熟悉良好异步编程模式的新开发人员很快就将信号量作为实现异步的通用机制例程同步运行。更糟糕的是,我看到他们中的许多人在主队列中使用这种信号量技术(我们永远不应该阻塞生产应用程序中的主队列)。
XCTestExpectation
我知道这里不是这种情况(发布这个问题时,没有像 这是可能需要阻塞主线程的信号量技术的罕见情况之一。
因此,我向这个原始问题的作者表示歉意,信号量技术对谁来说是合理的,我向所有看到这种信号量技术并考虑在他们的代码中应用它作为处理异步的一般方法的新开发人员写这个警告方法:警告十有八九,信号量技术不是遇到异步操作时的最佳方法。相反,请熟悉完成块/闭包模式,以及委托协议模式和通知。这些通常是处理异步任务的更好方法,而不是使用信号量使它们同步运行。通常有充分的理由将异步任务设计为异步行为,因此使用正确的异步模式而不是试图使它们同步行为。