Selain teknik semaphore yang dibahas secara mendalam dalam jawaban lain, kita sekarang dapat menggunakan XCTest di Xcode 6 untuk melakukan tes asinkron via XCTestExpectation
. Ini menghilangkan kebutuhan untuk semaphores saat menguji kode asinkron. Sebagai contoh:
- (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];
}
Demi pembaca masa depan, sementara teknik semaphore pengiriman adalah teknik yang luar biasa ketika benar-benar dibutuhkan, saya harus mengakui bahwa saya melihat terlalu banyak pengembang baru, tidak terbiasa dengan pola pemrograman asinkron yang baik, tertarik terlalu cepat ke semafor sebagai mekanisme umum untuk membuat asinkron. rutinitas berperilaku serempak. Lebih buruk lagi saya telah melihat banyak dari mereka menggunakan teknik semaphore ini dari antrian utama (dan kita tidak boleh memblokir antrian utama dalam aplikasi produksi).
Saya tahu ini tidak terjadi di sini (ketika pertanyaan ini diposting, tidak ada alat yang bagus seperti XCTestExpectation
; juga, di suite pengujian ini, kami harus memastikan tes tidak selesai sampai panggilan asinkron dilakukan). Ini adalah salah satu situasi langka di mana teknik semaphore untuk memblokir utas mungkin diperlukan.
Jadi dengan permintaan maaf saya kepada penulis pertanyaan asli ini, untuk siapa teknik semafornya baik, saya menulis peringatan ini kepada semua pengembang baru yang melihat teknik semafor ini dan mempertimbangkan menerapkannya dalam kode mereka sebagai pendekatan umum untuk berurusan dengan asinkron. metode: Diperingatkan bahwa sembilan dari sepuluh, teknik semaphore tidakpendekatan terbaik saat menghadapi operasi asinkron. Alih-alih, biasakan diri Anda dengan pola blok penutupan / penutupan, serta pola dan notifikasi delegate-protokol. Ini sering merupakan cara yang jauh lebih baik untuk menangani tugas-tugas yang tidak sinkron, daripada menggunakan semafor untuk membuatnya berperilaku serempak. Biasanya ada alasan bagus bahwa tugas asinkronik dirancang untuk berperilaku asinkron, jadi gunakan pola asinkron yang tepat daripada mencoba membuatnya berperilaku sinkron.
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
denganwhile (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; }