2011-06-03 3 views
29

मैं एक एनएसटीमर का उपयोग करता हूं जो हर सेकेंड को फायर करता है और एक लेबल अपडेट करता है जो किसी ईवेंट तक शेष समय प्रदर्शित करता है।आईओएस (प्रत्येक सेकेंड) पर समय-समय पर लेबल कैसे अपडेट करें?

मैं अभी तक ठीक काम करता हूं। समस्या यह है कि जब मैं TableView स्क्रॉल कर रहा हूं, तो मेरा लेबल अपडेट नहीं होता है, क्योंकि मेन थ्रेड को स्पर्श/स्क्रॉल ईवेंट द्वारा अवरोधित किया जाता है।

मैंने टाइमर के लिए दूसरा धागा बनाने के बारे में सोचा लेकिन मैं किसी भी पृष्ठभूमि थ्रेड से लेबल को अपडेट नहीं कर सका। मुझे इसे प्रदर्शन चयनकर्ता के साथ कतारबद्ध करना था ... मेन थ्रेड पर जहां यह पहले की तरह फंस जाएगा।

स्क्रॉल करते समय लेबल को अपडेट करने का कोई तरीका है?

उत्तर

44

समस्या यह है कि एक scheduledTimer जबकि मुख्य थ्रेड छूता ट्रैक कर रहा है कहा जाता है नहीं किया जाएगा है। आपको टाइमर को मुख्य रन लूप में शेड्यूल करने की आवश्यकता है।

तो बजाय कर

[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateLabel:) userInfo:nil repeats:YES]; 

उपयोग

NSTimer* timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(updateLabel:) userInfo:nil repeats:YES]; 
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
+0

मैंने सोचा था कि निर्धारित टाइमर विथटाइमइंटरवाल इसे वर्तमान रन लूप में जोड़ता है जो मुख्यRunLoop है क्योंकि मेरा एप्लिकेशन सिंगल थ्रेडेड है। –

+0

NSRunLoopCommonModes आपके टाइमर को तब भी कॉल कर देगा जब टेबल व्यू आपके स्पर्श को ट्रैक कर रहा है। – DHamrick

+0

@Alexander: यह इसे * डिफ़ॉल्ट * रन लूप मोड में जोड़ता है, सभी सामान्य * रन * रन लूप मोड नहीं मानते हैं। टच ट्रैकिंग के दौरान, डिफ़ॉल्ट लूप के अलावा कुछ मोड में रन लूप चलाया जा रहा है, इसलिए आपका टाइमर चेक नहीं किया जाता है। –

0

इस प्रयास करें:

self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateClock) userInfo:nil repeats:YES]; 
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; 
-3

आप भी GCD इस्तेमाल कर सकते हैं। तो

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
dispatch_async(queue, ^{ 
    [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateLabel:) userInfo:nil repeats:YES]; 
}); 

और अब चलाने के लिए अपनी updateLabel विधि

- (void) updateLabel:(id) sender { 
    NSString *text = @"some text"; 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     label.text = text; 
    }); 
} 

यह मुख्य थ्रेड में लेबल अद्यतन करेगा में।

+0

यह आपदा के लिए एक नुस्खा है। टाइमर उच्च यादृच्छिक समवर्ती कतार का उपयोग करने का फैसला करने वाले किसी भी यादृच्छिक (और संभावित अस्थायी) धागे के रनलोप के साथ पंजीकृत है, जिसका अर्थ है कि इसे कभी भी आग लगाने का मौका नहीं मिल सकता है। यदि आप जीसीडी के साथ देरी का उपयोग करना चाहते हैं, तो 'dispatch_after' का उपयोग करें। इस मामले में, आप मुख्य कतार में 1 सेकंड के बाद ब्लॉक को प्रेषित करने के लिए सेट अप करेंगे। –

+0

hrmm ... हाँ मुझे लगता है कि समझ में आता है। उस स्थिति में, प्रेषण कोड कैसा दिखता है? – brandontreb

+0

उदाहरण के लिए देखें https://gist.github.com/1006912। टिप्पणियाँ कोड लिखने के लिए एक बुरी जगह है। –