ความเห็นพ้องต้องกันใน Swift พร้อมการแยกข้อกังวล
การดำเนินการใน Swift เป็นวิธีที่มีประสิทธิภาพในการแยกความรับผิดชอบออกจากคลาสต่างๆ ขณะเดียวกันก็ติดตามความคืบหน้าและการพึ่งพา มีชื่ออย่างเป็นทางการว่า NSOperations และใช้ร่วมกับ OperationQueue
ก่อนอื่นอย่าลืมอ่านบทความของฉันเกี่ยวกับ "การทำงานพร้อมกันใน Swift" เพื่อให้คุณทราบพื้นฐานของคิวและการจัดส่ง การดำเนินงานมีหลายอย่างเหมือนกันกับบล็อกการจัดส่ง แต่มีข้อดีมากกว่าสองสามประการ มาดำดิ่งกัน!
การดำเนินการใน Swift คืออะไร?
โดยทั่วไปการดำเนินการจะรับผิดชอบต่องานซิงโครนัสเดียว มันเป็นคลาสนามธรรมและไม่เคยใช้โดยตรง คุณสามารถใช้คลาสย่อย BlockOperation
ที่ระบบกำหนดหรือสร้างคลาสย่อยของคุณเองได้ คุณสามารถเริ่มต้นการดำเนินการได้โดยการเพิ่มลงใน OperationQueue
หรือโดยการเรียกเมธอด start ด้วยตนเอง อย่างไรก็ตาม ขอแนะนำอย่างยิ่งให้มอบความรับผิดชอบอย่างเต็มที่ให้กับ OperationQueue
ในการจัดการรัฐ
การใช้ BlockOperation
ที่ระบบกำหนดมีลักษณะดังนี้:
let blockOperation = BlockOperation {
print("Executing!")
}
let queue = OperationQueue()
queue.addOperation(blockOperation)
ซึ่งสามารถทำได้โดยการเพิ่มบล็อกลงในคิวโดยตรง:
queue.addOperation {
print("Executing!")
}
งานที่กำหนดจะถูกเพิ่มใน OperationQueue
ซึ่งจะเริ่มดำเนินการโดยเร็วที่สุด
การสร้างการดำเนินการแบบกำหนดเอง
คุณสร้างการแยกข้อกังวลด้วยการดำเนินการแบบกำหนดเอง ตัวอย่างเช่น คุณสามารถสร้างการใช้งานที่กำหนดเองสำหรับการนำเข้าเนื้อหา และอีกวิธีหนึ่งสำหรับการอัปโหลดเนื้อหา
ตัวอย่างโค้ดต่อไปนี้แสดงคลาสย่อยที่กำหนดเองสำหรับการนำเข้าเนื้อหา:
final class ContentImportOperation: Operation {
let itemProvider: NSItemProvider
init(itemProvider: NSItemProvider) {
self.itemProvider = itemProvider
super.init()
}
override func main() {
guard !isCancelled else { return }
print("Importing content..")
// .. import the content using the item provider
}
}
ชั้นเรียนรับผู้ให้บริการรายการและนำเข้าเนื้อหาภายในวิธีการหลัก ฟังก์ชัน main()
เป็นวิธีเดียวที่คุณต้องเขียนทับสำหรับการดำเนินการแบบซิงโครนัส เพิ่มการดำเนินการลงในคิว และตั้งค่าบล็อคการดำเนินการให้เสร็จสิ้นเพื่อติดตามความสำเร็จ:
let fileURL = URL(fileURLWithPath: "..")
let contentImportOperation = ContentImportOperation(itemProvider: NSItemProvider(contentsOf: fileURL)!)
contentImportOperation.completionBlock = {
print("Importing completed!")
}
queue.addOperation(contentImportOperation)
// Prints:
// Importing content..
// Importing completed!
การดำเนินการนี้จะย้ายตรรกะทั้งหมดของคุณในการนำเข้าเนื้อหาไปยังชั้นเรียนเดียว ซึ่งคุณสามารถติดตามความคืบหน้า ความสมบูรณ์ และคุณสามารถเขียนการทดสอบได้อย่างง่ายดาย
สถานะต่าง ๆ ของการดำเนินการ
การดำเนินการสามารถมีได้หลายสถานะ ขึ้นอยู่กับสถานะการดำเนินการในปัจจุบัน
- พร้อม:พร้อมแล้วที่จะเริ่ม
- กำลังดำเนินการ:งานกำลังทำงานอยู่
- เสร็จสิ้น:เมื่อกระบวนการเสร็จสิ้น
- ยกเลิกแล้ว:งานถูกยกเลิก
สิ่งสำคัญคือต้องรู้ว่าการดำเนินการสามารถดำเนินการได้เพียงครั้งเดียวเท่านั้น เมื่อใดก็ตามที่อยู่ในสถานะเสร็จสิ้นหรือยกเลิก คุณจะไม่สามารถรีสตาร์ทอินสแตนซ์เดิมได้อีกต่อไป
ภายในการใช้งานแบบกำหนดเอง คุณต้องตรวจสอบสถานะที่ถูกยกเลิกด้วยตนเองก่อนดำเนินการเพื่อให้แน่ใจว่างานจะถูกยกเลิก โปรดทราบว่าการแข่งขันของข้อมูลสามารถเกิดขึ้นเมื่อการดำเนินการเริ่มต้นและยกเลิกพร้อมกัน คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการแข่งขันของข้อมูลได้ในบล็อกโพสต์ของฉัน “Thread Sanitizer อธิบาย: Data Races in Swift”
OperationQueue
จะลบงานออกจากคิวโดยอัตโนมัติเมื่อเสร็จสิ้น ซึ่งเกิดขึ้นทั้งหลังการดำเนินการหรือหลังการยกเลิก
การใช้การพึ่งพาอาศัยกัน
ประโยชน์ของการใช้การดำเนินการคือการใช้การพึ่งพา คุณสามารถเพิ่มการพึ่งพาระหว่างสองอินสแตนซ์ได้อย่างง่ายดาย ตัวอย่างเช่น หากต้องการเริ่มอัปโหลดหลังจากนำเข้าเนื้อหาแล้ว:
let fileURL = URL(fileURLWithPath: "..")
let contentImportOperation = ContentImportOperation(itemProvider: NSItemProvider(contentsOf: fileURL)!)
contentImportOperation.completionBlock = {
print("Importing completed!")
}
let contentUploadOperation = UploadContentOperation()
contentUploadOperation.addDependency(contentImportOperation)
contentUploadOperation.completionBlock = {
print("Uploading completed!")
}
queue.addOperations([contentImportOperation, contentUploadOperation], waitUntilFinished: true)
// Prints:
// Importing content..
// Uploading content..
// Importing completed!
// Uploading completed!
การอัปโหลดจะเริ่มหลังจากการนำเข้าเนื้อหาเสร็จสิ้นแล้วเท่านั้น ไม่คำนึงถึงการยกเลิก ซึ่งหมายความว่าหากการดำเนินการนำเข้ายกเลิก การอัปโหลดก็จะยังเริ่มต้นอยู่
คุณต้องดำเนินการตรวจสอบเพื่อดูว่าการอ้างอิงถูกยกเลิกหรือไม่:
final class UploadContentOperation: Operation {
override func main() {
guard !dependencies.contains(where: { $0.isCancelled }), !isCancelled else {
return
}
print("Uploading content..")
}
}
บทสรุป
ฉันหวังว่าคุณจะตื่นเต้นที่จะเริ่มดำเนินการใน Swift เป็นอัญมณีที่ซ่อนอยู่ซึ่งช่วยให้คุณสามารถแยกข้อกังวล เพิ่มการพึ่งพาระหว่างงาน และติดตามความสำเร็จได้