जैसा कि यहां उल्लेख किया गया है और अन्य एसओ सवालों के जवाब में, आप beginBackgroundTask
केवल तब उपयोग नहीं करना चाहते हैं जब आपका ऐप पृष्ठभूमि में जाएगा; इसके विपरीत, आप के लिए एक पृष्ठभूमि कार्य का उपयोग करना चाहिए किसी भी समय लेने वाली आपरेशन जिसका पूरा होने आप अगर एप्लिकेशन भी सुनिश्चित करना चाहते हैं करता है पृष्ठभूमि में जाने।
इसलिए आपका कोड कॉलिंग beginBackgroundTask
और endBackgroundTask
सुसंगत रूप से एक ही बॉयलरप्लेट कोड के दोहराव के साथ समाप्त होने की संभावना है । इस पुनरावृत्ति को रोकने के लिए, यह निश्चित रूप से उचित है कि बॉयलरप्लेट को कुछ एकल एन्कैप्सुलेटेड इकाई में पैकेज करना चाहिए।
मुझे ऐसा करने के लिए कुछ मौजूदा उत्तर पसंद हैं, लेकिन मुझे लगता है कि ऑपरेशन उपवर्ग का उपयोग करने का सबसे अच्छा तरीका है:
आप किसी भी OperationQueue पर ऑपरेशन को संलग्न कर सकते हैं और उस कतार में हेरफेर कर सकते हैं जैसा कि आप फिट देखते हैं। उदाहरण के लिए, आप कतार में किसी भी मौजूदा परिचालन को समय से पहले रद्द करने के लिए स्वतंत्र हैं।
यदि आपके पास करने के लिए एक से अधिक चीजें हैं, तो आप कई पृष्ठभूमि कार्य संचालन को चेन कर सकते हैं। संचालन समर्थन निर्भरताएँ।
ऑपरेशन कतार एक पृष्ठभूमि कतार हो सकती है (और होनी चाहिए); इस प्रकार, आपकी कार्य अंदर एसिंक्रोनस कोड प्रदर्शन के बारे में चिंता करने की कोई जरूरत है, क्योंकि ऑपरेशन है है अतुल्यकालिक कोड। (वास्तव में, यह ऑपरेशन के अंदर एक और स्तर के अतुल्यकालिक कोड को निष्पादित करने का कोई मतलब नहीं है , क्योंकि ऑपरेशन इससे पहले कि कोड भी शुरू हो सकता है। यदि आपको ऐसा करने की आवश्यकता है, तो आप दूसरे ऑपरेशन का उपयोग करेंगे।)
यहाँ एक संभावित ऑपरेशन उपवर्ग है:
class BackgroundTaskOperation: Operation {
var whatToDo : (() -> ())?
var cleanup : (() -> ())?
override func main() {
guard !self.isCancelled else { return }
guard let whatToDo = self.whatToDo else { return }
var bti : UIBackgroundTaskIdentifier = .invalid
bti = UIApplication.shared.beginBackgroundTask {
self.cleanup?()
self.cancel()
UIApplication.shared.endBackgroundTask(bti) // cancellation
}
guard bti != .invalid else { return }
whatToDo()
guard !self.isCancelled else { return }
UIApplication.shared.endBackgroundTask(bti) // completion
}
}
यह स्पष्ट होना चाहिए कि इसका उपयोग कैसे किया जाए, लेकिन अगर ऐसा नहीं है, तो कल्पना करें कि हमारे पास एक वैश्विक ऑपरेशन क्यू है:
let backgroundTaskQueue : OperationQueue = {
let q = OperationQueue()
q.maxConcurrentOperationCount = 1
return q
}()
तो कोड के एक विशिष्ट समय लेने वाले बैच के लिए हम कहेंगे:
let task = BackgroundTaskOperation()
task.whatToDo = {
// do something here
}
backgroundTaskQueue.addOperation(task)
यदि आपके समय लेने वाले कोड के बैच को चरणों में विभाजित किया जा सकता है, तो आप अपना कार्य रद्द होने पर जल्दी से झुकना चाहते हैं। उस स्थिति में, बस समय से पहले बंद हो जाना। ध्यान दें कि बंद के भीतर से कार्य के लिए आपका संदर्भ कमजोर होना चाहिए या आपको एक चक्र बनाए रखना होगा। यहाँ एक कृत्रिम चित्रण है:
let task = BackgroundTaskOperation()
task.whatToDo = { [weak task] in
guard let task = task else {return}
for i in 1...10000 {
guard !task.isCancelled else {return}
for j in 1...150000 {
let k = i*j
}
}
}
backgroundTaskQueue.addOperation(task)
यदि आपके पास सफाई कार्य करने की स्थिति में पृष्ठभूमि का कार्य समय से पहले ही रद्द हो जाता है, तो मैंने एक वैकल्पिक cleanup
हैंडलर संपत्ति (पूर्ववर्ती उदाहरणों में उपयोग नहीं की गई) प्रदान की है। इसमें शामिल नहीं होने के लिए कुछ अन्य उत्तरों की आलोचना की गई।