Diğer cevaplarda ayrıntılı olarak ele alınan semafor tekniğine ek olarak, artık Xcode 6'da XCTest'i kullanarak eşzamansız testler yapabiliyoruz XCTestExpectation
. Bu, eşzamansız kod test edilirken semafor ihtiyacını ortadan kaldırır. Örneğin:
- (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];
}
Gelecekteki okuyucular uğruna, sevk semaforu tekniği kesinlikle ihtiyaç duyulduğunda harika bir teknik olsa da, itiraf etmeliyim ki, asenkron programlama modellerine aşina olmayan çok fazla yeni geliştirici, asenkron yapmak için genel bir mekanizma olarak semaforlara çok çabuk yaklaşıyor rutinler eşzamanlı davranır. Daha da kötüsü, bu semafor tekniğini ana kuyruktan kullandığını gördüm (ve üretim uygulamalarındaki ana kuyruğu asla engellememeliyiz).
Burada böyle olmadığını biliyorum (bu soru gönderildiğinde, böyle güzel bir araç yoktu XCTestExpectation
; Ayrıca, bu test paketlerinde, eşzamansız çağrı yapılana kadar testin bitmediğinden emin olmalıyız). Bu, ana ipliği bloke etmek için semafor tekniğinin gerekli olabileceği nadir durumlardan biridir.
Bu yüzden, semafor tekniğinin sağlam olduğu bu orijinal sorunun yazarından özür dilerim, bu uyarıyı bu semafor tekniğini gören tüm yeni geliştiricilere yazıyorum ve kodunda asenkron ile uğraşmak için genel bir yaklaşım olarak görmeyi düşünüyorum yöntem: on üzerinden dokuz kez, semafor teknik olduğunu forewarned değileşzamansız işlemlerle karşılaşırken en iyi yaklaşım. Bunun yerine, tamamlama bloğu / kapatma kalıplarının yanı sıra delege protokolü kalıplarını ve bildirimlerini öğrenin. Bunlar, eşzamanlı davranmalarını sağlamak için semaforlar kullanmak yerine, asenkron görevlerle uğraşmak için genellikle çok daha iyi yollardır. Genellikle eşzamansız görevlerin eşzamansız davranacak şekilde tasarlanmasının iyi nedenleri vardır, bu nedenle eşzamanlı davranmaya çalışmak yerine doğru eşzamansız deseni kullanın.
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
olanwhile (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; }