다른 답변에서 철저하게 다루는 세마포어 기술 외에도 이제 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. 또한 이러한 테스트 스위트에서는 비동기 호출이 완료 될 때까지 테스트가 완료되지 않아야합니다). 이것은 메인 스레드를 차단하기위한 세마포어 기술이 필요할 수있는 드문 상황 중 하나입니다.
따라서 세마포어 기술이 적합한이 원래 질문의 저자에게 사과를 드리며이 세마포어 기술을보고 비동기식 처리를위한 일반적인 접근 방식으로 코드에 적용하는 것을 고려하는 모든 새로운 개발자 에게이 경고를 씁니다. 방법 : 10 명 중 아홉 번, 세마포어 기술은 미리 양해 없습니다비동기 작업을 처리 할 때 가장 좋은 방법입니다. 대신 완료 프로토콜 / 클로저 패턴과 델리게이트 프로토콜 패턴 및 알림을 숙지하십시오. 이들은 종종 세마포어를 사용하여 동 기적으로 동작하는 것보다 비동기 작업을 처리하는 훨씬 좋은 방법입니다. 일반적으로 비동기 타스크가 비동기 적으로 작동하도록 설계된 이유는 충분하므로 동 기적으로 작동하지 말고 올바른 비동기 패턴을 사용하십시오.
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; }