एनएसटीमर को थ्रेड के रनलोप के लिए निर्धारित किया गया है। प्रश्न के संहिता में, जीसीडी द्वारा प्रेषित धागे का रनलोप नहीं चल रहा है। आपको इसे मैन्युअल रूप से प्रारंभ करना होगा और रन लूप से बाहर निकलने का एक तरीका होना चाहिए, इसलिए आपको एनएसटीमर का संदर्भ रखना चाहिए, और उचित समय में इसे अमान्य करना चाहिए।
एनएसटीमर के पास लक्ष्य के लिए मजबूत संदर्भ है, इसलिए लक्ष्य टाइमर के लिए मजबूत संदर्भ नहीं हो सकता है, और रनलोप टाइमर के लिए मजबूत संदर्भ है।
weak var weakTimer: Timer?
func configurateTimerInBackgroundThread(){
DispatchQueue.global().async {
// Pause program execution in Xcode, you will find thread with this name
Thread.current.name = "BackgroundThreadWithTimer"
// This timer is scheduled to current run loop
self.weakTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(runTimer), userInfo: nil, repeats: true)
// Start current runloop manually, otherwise NSTimer won't fire.
RunLoop.current.run(mode: .defaultRunLoopMode, before: Date.distantFuture)
}
}
@objc func runTimer(){
NSLog("Timer is running in mainThread: \(Thread.isMainThread)")
}
यदि भविष्य में टाइमर अमान्य हो गया है, तो एक्सकोड में फिर से प्रोग्राम निष्पादन रोकें, आपको पता चलेगा कि थ्रेड चला गया है।
बेशक, जीसीडी द्वारा भेजे गए धागे में रनलोप है। जीसीडी आंतरिक रूप से थ्रेड उत्पन्न करता है और पुन: उपयोग करता है, वहां थ्रेडर कॉलर के लिए अज्ञात होते हैं। यदि आप इसे सुरक्षित महसूस नहीं करते हैं, तो आप थ्रेड का उपयोग कर सकते हैं। डरो मत, कोड बहुत आसान है।
दरअसल, मैं पिछले हफ्ते एक ही चीज़ की कोशिश करता हूं और पूछताछ के साथ असफल हो जाता हूं, फिर मुझे यह पृष्ठ मिला। मैं हारने से पहले एनएसटीएचड की कोशिश करता हूं। यह काम करता हैं। तो जीसीडी में एनएसटीमर क्यों काम नहीं कर सकता है? यह होना चाहिए। NSTimer कैसे काम करता है यह जानने के लिए runloop's document पढ़ें।
NSTimer के साथ काम करने का प्रयोग करें NSThread:
func configurateTimerInBackgroundThread(){
let thread = Thread.init(target: self, selector: #selector(addTimerInBackground), object: nil)
thread.name = "BackgroundThreadWithTimer"
thread.start()
}
@objc func addTimerInBackground() {
self.weakTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(runTimer), userInfo: nil, repeats: true)
RunLoop.current.run(mode: .defaultRunLoopMode, before: Date.distantFuture)
}
केविन की 2 जवाब निम्नलिखित एक और विकल्प, मैं MSWeakTimer साथ NSTimer (github.com/mindsnacks/MSWeakTimer) की जगह मेरी मुद्दों को हल किया, और सिर्फ dispatch_get_global_queue पारित कर दिया (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) प्रेषण के रूप में। –
ग्रेट सारांश। सुपर धन्यवाद। अगर मैं सही ढंग से समझता हूं: 1. क्या आप कह रहे हैं कि कोई भी जीसीडी प्रेषण धागा मुख्य थ्रेड के लिए ** को छोड़कर एक रन लूप ** है? 2. यदि सही है तो प्रेषण के बारे में कैसे? यह रनलॉप के बिना कैसे प्रक्रिया करेगा? या यह है कि यह एक जीसीडी जागरूक तंत्र में भी लागू किया गया है? – Honey
@ हनी डिस्पैच थ्रेड में रन लूप नहीं हैं। मुख्य धागा एक प्रेषण धागा नहीं है (ठीक है, जब तक कि आप 'dispatch_main() 'का उपयोग नहीं कर रहे हैं, और यदि ऐसा है, तो इसमें कोई रनलॉप नहीं है, लेकिन आप संभवतः ऐसा नहीं कर रहे हैं)। मुख्य धागा का रनलोप रनयूप के सामान्य ऑपरेशन के हिस्से के रूप में मुख्य कतार को स्पष्ट रूप से निकालने के लिए जीसीडी के साथ एकीकृत करता है। 'dispatch_after' जीसीडी का हिस्सा है (इसलिए नाम में" प्रेषण "शब्द), इसमें रनलोप्स के साथ कुछ भी नहीं है। –