다른 답변에서 철저하게 다루는 세마포어 기술 외에도 이제 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]]; }