2016-01-17 29 views
6

में एक बार काम करता है मेरे पास http अनुरोध है, और यदि मुझे सही प्रतिक्रिया मिलती है, तो मैं एक टाइमर शुरू करना चाहता हूं जो प्रत्येक सेकेंड में एक फ़ंक्शन को सक्रिय करता है। वह फ़ंक्शन भी एक http अनुरोध है।क्यों NSTimer तेजी से

इस

जैसा कि आप देख, मैं एक समारोह में कहा जाता checkIfThereAreResponses

कि समारोह में फोन कर रहा हूँ, मैं एक प्रिंट बयान है, और है कि प्रिंट बयान है टाइमर आग

if let data = data { 
     do{ 
      let resultJSON = try NSJSONSerialization.JSONObjectWithData(data, options: []) 
      requestClient.id = resultJSON["id"] as! Double 
      self.timerResponse = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "checkIfThereAreResponeses", userInfo: nil, repeats: true) 
      self.timerResponse!.fire() 
     }catch{ 
     } 
    } 

मेरी कोड है केवल एक बार मुद्रित किया जा रहा है, हालांकि मेरा टाइमर प्रत्येक 1 सेकंड

मेरे पास क्या गुम है?

और इस समारोह

func checkIfThereAreResponeses(){ 
    if (requestClient!.id != nil) { 
     let url = NSURL(string: "http://localhost:blablabla") 
     let request = NSMutableURLRequest(URL: url) 
     request.HTTPMethod = "POST" 

     let session = NSURLSession.sharedSession() 

     task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in 
      if let error = error { 
       print("error = \(error)") 
      } 



      if let data = data { 
       do { 
        let resultJSONArray = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! NSArray 
     bla bla bla 

       }catch { 
        print("no responses yet = \(error)") 
       } 
      } 
     }) 
     task!.resume() 
    }else { 
     print("not yet ") 
    } 
} 

प्रिंट मैं प्राप्त होने वाले सिर्फ एक बारno response yet

+0

मैं इस मुद्दे को पुन: पेश नहीं कर सकता, 'checkIfThereAreResponeses' के अंदर पहला कथन 'प्रिंट' है? – luk2302

+0

@ luk2302 अभी तक यह इसके अंदर है। – sarah

+0

लेकिन क्या यह * पहला * है? वास्तविक 'checkIfThereAreResponeses' को देखने में मददगार हो सकता है! – luk2302

उत्तर

7

है आप पूरा होने हैंडलर में इस कोड है, तो है, यह सिफारिश की है NSTimer मुख्य में चल रहा है धागा तो यह कारण हो सकता है।

dispatch_async(dispatch_get_main_queue(), { 
    // Your timer logic here 
}) 

एप्पल डॉक्स का कहना है: रन छोरों के साथ संयोजन के रूप में

टाइमर काम आप की तरह कुछ जरूरत हो सकती है। एक टाइमर प्रभावी ढंग से उपयोग करने के लिए, आपको पता होना चाहिए कि कैसे रन लूप संचालित होते हैं-NSRunLoop देखें।

(NSTimer)

NSRunLoop वर्ग आम तौर पर धागे की सुरक्षित और अपने तरीकों केवल वर्तमान धागा के संदर्भ में बुलाया जाना चाहिए नहीं माना जाता है। आपको किसी NSRunLoop ऑब्जेक्ट को किसी भिन्न थ्रेड में चलने वाली विधियों को कॉल करने का प्रयास नहीं करना चाहिए, क्योंकि ऐसा करने से अप्रत्याशित परिणाम हो सकता है।

(NSRunLoop)

+0

आप 'dispatch_async करने के लिए अपने कोड को बदलने के लिए impling कर रहे हैं(), { self.timerResponse = NSTimer.scheduledTimerWithTimeInterval (1, लक्ष्य: स्वयं, चयनकर्ता:" checkIfThereAreResponeses ", userInfo: शून्य, दोहराता है: सच) self.timerResponse !फायर() } ) '? – sarah

+0

@ सराह हां, ऐसा कुछ जवाब का निहितार्थ है। – luk2302

+0

क्या मेरे पास इस समस्या को हल करने में मेरा ज्ञान बढ़ाने का एक लिंक हो सकता है? – sarah

2

एक NSTimer एक runloop पर निर्धारित किया जा रहा द्वारा काम करता है। यदि आप इस विधि को पूरा करने में कॉल करते हैं, सत्र के हैंडलर, यह थ्रेड के रनूप पर निर्धारित किया जाएगा कि पूरा होने पर हैंडलर वर्तमान में चल रहा है। चूंकि इस धागे का स्वामित्व आपके स्वामित्व में नहीं है, लेकिन सिस्टम द्वारा, इसे सिस्टम द्वारा निपटाया जाएगा। यह पूरा होने के तुरंत बाद हो सकता है हैंडलर निष्पादित किया जाता है, या यह बहुत बाद में हो सकता है। धागे के साथ, रनलोप भी चला गया है, इस प्रकार, आपका टाइमर कभी भी, कभी-कभी या दो बार आग नहीं सकता है; वास्तव में कोई बताना नहीं है क्योंकि यह इस बात पर निर्भर करता है कि सिस्टम थ्रेड को कब हटा देगा।

इसलिए, आप एक धागा आप खुद पर टाइमर बनाना चाहिए, या, आसान, (dispatch_get_main_queue() अपने दोस्त है) मुख्य थ्रेड पर टाइमर के निर्माण प्रेषण। एक और विकल्प +timerWithTimeInterval... विधियों में से एक के साथ एनएसटीमर बनाने के लिए है और फिर इसे [NSRunloop mainRunloop] addTimer: yourTimer forMode NSRunLoopCommonModes] का उपयोग करके मुख्य रनलोप में जोड़ें। याद रखें कि टाइमर आपके चयनकर्ता को उसी थ्रेड पर कॉल करेगा जिस पर यह चल रहा है।

एक साइड नोट के रूप में, एक सर्वर को मतदान करना मोबाइल डिवाइस पर जाने का सबसे अच्छा तरीका नहीं हो सकता है। यदि आप सर्वर को नियंत्रित करते हैं, तो इसके लिए नया डेटा होने पर डिवाइस पर पुश अधिसूचना भेजना बेहतर हो सकता है। यह डिवाइस पर बैटरी को बचाएगा, और आपके सर्वर पर लोड को कम करेगा। हालांकि, अगर आप सर्वर को नियंत्रित नहीं करते हैं, तो यह हासिल करने के लिए और अधिक जटिल होगा, और फिर मतदान एक अच्छा समझौता हो सकता है।

संबंधित मुद्दे