2011-03-03 38 views
16

मुझे यह बिल्कुल समझ में नहीं आता है लेकिन मेरे ऐप में NSTimer पृष्ठभूमि में चल रहा है। मेरे पास टाइमर द्वारा चलाए गए मेहोड में NSLog है और यह पृष्ठभूमि में होने पर लॉगिंग कर रहा है। यह आईओएस 4.2.1 के साथ आईफोन 4 पर है। मैंने Info.plist में स्थान पृष्ठभूमि समर्थन घोषित कर दिया है।पृष्ठभूमि पर एनएसटीमर काम कर रहा है

मैं यहाँ और कहीं और डॉक्स और कई चर्चाओं पढ़ सकते हैं और यह संभव नहीं होना चाहिए। क्या यह एक आईओएस बग है? या अनियंत्रित सुविधा? मैं इसका उपयोग नहीं करना चाहता हूं और निकट भविष्य में पता लगाना चाहता हूं, उदाहरण के लिए आईओएस 4.3 के आने के साथ कि ऐप्पल चुपचाप इसे "तय" करता है और ऐप काम नहीं करेगा।

क्या कोई इसके बारे में और अधिक जानता है?

उत्तर

31

NSTimer जब भी मुख्य runloop चल रहा है आग जा रहा है। ऐप्पल कोई वादा नहीं करता है कि मुझे टाइम्स को अनदेखा करने या मुख्य रनलोप को चलाने से रोकने के लिए पता है। जब आप पृष्ठभूमि में जाते हैं तो अपने टाइमर को अनदेखा करना और संसाधनों को रिलीज़ करना आपकी ज़िम्मेदारी है। ऐप्पल आपके लिए ऐसा नहीं करेगा। हालांकि, वे आपको चलाने के लिए मार सकते हैं जब आपको बहुत अधिक सेकंड का उपयोग नहीं करना चाहिए या नहीं।

प्रणाली है जिसे किसी ऐप जब यह करने के लिए अधिकृत नहीं है चलाने के लिए अनुमति देगा में कई छेद हैं। ओएस के लिए इसे रोकने के लिए यह बहुत महंगा होगा। लेकिन आप इस पर भरोसा नहीं कर सकते हैं। पृष्ठभूमि निष्पादन मोड में रहते हुए

+0

ठीक है, यह मेरे लिए पर्याप्त जवाब है। धन्यवाद। मुझे नहीं पता था कि मुझे कुछ याद आया या नहीं। मैं निश्चित रूप से इसका उपयोग नहीं करूंगा। – JakubM

8

आप can एक टाइमर आग की है। कुछ चाल हैं:

  • आपको beginBackgroundTaskWithExpirationHandler के साथ पृष्ठभूमि निष्पादन में चयन करने की आवश्यकता है।
  • यदि आप पृष्ठभूमि थ्रेड पर NSTimer बनाते हैं, तो आपको इसे मैन्युअल रूप से mainRunLoop में जोड़ना होगा।

- (void)viewDidLoad 
{ 
    // Avoid a retain cycle 
    __weak ViewController * weakSelf = self; 

    // Declare the start of a background task 
    // If you do not do this then the mainRunLoop will stop 
    // firing when the application enters the background 
    self.backgroundTaskIdentifier = 
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 

     [[UIApplication sharedApplication] endBackgroundTask:self.backgroundIdentifier]; 
    }]; 

    // Make sure you end the background task when you no longer need background execution: 
    // [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier]; 


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Since we are not on the main run loop this will NOT work: 
     [NSTimer scheduledTimerWithTimeInterval:0.5 
             target:self 
             selector:@selector(timerDidFire:) 
             userInfo:nil 
             repeats:YES]; 

     // This is because the |scheduledTimerWithTimeInterval| uses 
     // [NSRunLoop currentRunLoop] which will return a new background run loop 
     // which will not be currently running. 
     // Instead do this: 
     NSTimer * timer = 
     [NSTimer timerWithTimeInterval:0.5 
           target:weakSelf 
           selector:@selector(timerDidFire:) 
           userInfo:nil 
           repeats:YES]; 

     [[NSRunLoop mainRunLoop] addTimer:timer 
            forMode:NSDefaultRunLoopMode]; 
     // or use |NSRunLoopCommonModes| if you want the timer to fire while scrolling 
    }); 
} 

- (void) timerDidFire:(NSTimer *)timer 
{ 
    // This method might be called when the application is in the background. 
    // Ensure you do not do anything that will trigger the GPU (e.g. animations) 
    // See: http://developer.apple.com/library/ios/DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW47 
    NSLog(@"Timer did fire"); 
} 

नोट्स

  • ऐप केवल मिल ~ पृष्ठभूमि निष्पादन के 10 मिनट - इस के बाद टाइमर फायरिंग बंद हो जाएगा।
  • iOS 7 के रूप में डिवाइस है जब बंद कर दिया यह लगभग तुरंत अग्रभूमि एप्लिकेशन निलंबित कर देगा। आईओएस 7 ऐप लॉक होने के बाद टाइमर आग नहीं लगेगा।
+0

कोड की महान शांति, इससे मुझे अपना ऐप पूरा करने में मदद मिलेगी, THNX :)। एक छोटा सा सवाल, आप इस विधि को क्या कहते हैं जब एप्लिकेशन पृष्ठभूमि में होता है। " मैं इसे 3 घंटे में सर्वर से डेटा अपडेट करने के लिए उपयोग करना चाहता हूं। क्या कोई बेहतर दृष्टिकोण है? – MQoder

+1

आपका एप्लिकेशन केवल पृष्ठभूमि में डाले जाने पर अधिकतम 10 मिनट तक चलाएगा। आईओएस 7 के रूप में ये 10 मिनट अलग हो सकते हैं। आप आईओएस 7 के नए पृष्ठभूमि मोड का उपयोग करने में सक्षम हो सकते हैं: बड़े अपलोड/डाउनलोड या चुपके धक्का के लिए पृष्ठभूमि हस्तांतरण को आप दूरस्थ रूप से अपनाने के लिए। – Robert

+1

यह कोड नमूना ऐप की अग्रभूमि/पृष्ठभूमि स्थिति और वैश्विक कतार बनाम मुख्य कतार के बीच एक भ्रम का सुझाव देता है। एक वैश्विक कतार में टाइमर के शेड्यूलिंग को प्रेषित करने की कोई आवश्यकता नहीं है। बस सामान्य कतार पर टाइमर शेड्यूल करें, जैसे कि सामान्य, और 'स्टार्टबैकग्राउंड टास्कविथ एक्सपेरेशन हैंडलर' ऐप को कुछ मिनटों तक जीवंत रखेगा। – Rob

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