นอกจากนี้ยังมีเทคนิคสัญญาณครอบคลุมอย่างละเอียดถี่ถ้วนในคำตอบอื่น ๆ ตอนนี้เราสามารถใช้ XCTest ใน Xcode 6 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
ในชุดทดสอบเหล่านี้เราต้องแน่ใจว่าการทดสอบไม่เสร็จจนกว่าจะมีการโทรแบบอะซิงโครนัส) นี่เป็นหนึ่งในสถานการณ์ที่หายากเหล่านั้นซึ่งอาจมีเทคนิคเซมาฟอร์สำหรับบล็อกเธรดหลักอาจจำเป็น
ดังนั้นด้วยคำขอโทษของฉันถึงผู้เขียนคำถามต้นฉบับนี้ซึ่งเทคนิคสัญญาณเป็นเสียงฉันเขียนคำเตือนนี้ให้กับนักพัฒนาใหม่ทุกคนที่เห็นเทคนิคสัญญาณนี้และพิจารณาใช้ในรหัสของพวกเขาเป็นแนวทางทั่วไปในการจัดการกับอะซิงโครนัส วิธีการ: ได้รับการเตือนล่วงหน้าว่าเก้าครั้งจากสิบเทคนิคสัญญาณไม่ได้วิธีที่ดีที่สุดเมื่อพบการดำเนินการแบบอะซิงโครนัส ให้ทำความคุ้นเคยกับรูปแบบบล็อก / การปิดที่สมบูรณ์รวมถึงรูปแบบของผู้รับมอบสิทธิ์และการแจ้งเตือน สิ่งเหล่านี้มักจะเป็นวิธีที่ดีกว่าในการจัดการกับภารกิจแบบอะซิงโครนัสมากกว่าการใช้เซมาฟอร์ โดยทั่วไปมีเหตุผลที่ดีที่งานแบบอะซิงโครนัสถูกออกแบบมาให้ทำงานแบบอะซิงโครนัสดังนั้นให้ใช้รูปแบบอะซิงโครนัสที่ถูกต้องแทนที่จะพยายามทำแบบอะซิงโครนัส
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
ด้วยwhile (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; }