7

के लिए पर्यवेक्षक पैटर्न मैं एमवीसी मॉडल के आधार पर स्टॉपवॉच को लागू करने की कोशिश कर रहा हूं।स्टॉपवॉच

स्टॉपवॉच एनएसटीमर का चयनकर्ता -(void) tick प्रत्येक टाइमआउट कहलाता है।

मैंने पुन: प्रयोज्यता के लिए स्टॉपवॉच को मॉडल के रूप में बनाने की कोशिश की है, लेकिन मैंने प्रत्येक टिक के लिए व्यू कंट्रोलर को अपडेट करने के तरीके के बारे में कुछ डिज़ाइन समस्याओं में भाग लिया है।

सबसे पहले मैंने टिक विधि के साथ एक प्रोटोकॉल बनाया और दृश्य नियंत्रक को इसके प्रतिनिधि बनाया। व्यू कंट्रोलर फिर प्रत्येक टिक पर टाइमर के गुणों के आधार पर विचारों को अपडेट करता है। elapsedTime एक पठनीय NSTimeInterval है।

यह काम करता है, लेकिन मुझे लगता है कि यह खराब डिजाइन हो सकता है। मैं एक उद्देश्य-सी/कोको टच शुरुआत कर रहा हूँ। क्या मुझे केवीओ की तरह कुछ इस्तेमाल करना चाहिए? या मॉडल नियंत्रक को सूचित करने के लिए मॉडल के लिए एक और अधिक सुरुचिपूर्ण समाधान है कि elapsedTime बदल गया है?

+1

अच्छा पहला सवाल! एसओ में आपका स्वागत है! –

+0

टाइमर और दृश्य नियंत्रक के बीच संबंध वास्तव में क्या है? क्या टाइमर वीसी के स्वामित्व में है? –

+0

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

उत्तर

0

हाल ही में, मैं सादे पुराने @selector के बजाय ब्लॉक का उपयोग कर उपयोग कर रहा हूं। यह बेहतर और कोड बनाता है और तर्क को उसी स्थान पर रखता है।

कोई मूल ब्लॉक NSTimer में समर्थन नहीं है, लेकिन मैं वापसी चयनकर्ता के बिना से https://gist.github.com/250662/d4f99aa9bde841107622c5a239e0fc6fa37cb179

एक वर्ग का इस्तेमाल किया है, तो आप एक स्थान में कोड रखें:

__block int seconds = 0; 
    NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:1 
               repeats:YES 
               usingBlock:^(NSTimer *timer) { 

               seconds++; 
               // Update UI 

               if (seconds>=60*60*2) { 
                [timer invalidate]; 
               } 




}]; 
5

टाइमर के लिए एक अच्छा तरीका है सुनिश्चित करें कि आप समय-समय पर अपना यूजर इंटरफेस अपडेट करें, लेकिन समय का ट्रैक रखने के लिए इसका इस्तेमाल न करें। NSTimer can drift, और यदि आप सेकेंड जमा करने के लिए टाइमर का उपयोग करते हैं तो कोई भी छोटी त्रुटियां जमा हो सकती हैं।

इसके बजाय, अपने यूआई को अपडेट करने वाली विधि को ट्रिगर करने के लिए एनएसटीमर का उपयोग करें, लेकिन एनएसडीएट का उपयोग करके वास्तविक समय प्राप्त करें। एनएसडीएटी आपको मिलीसेकंद रिज़ॉल्यूशन देगा; यदि आपको वास्तव में उससे बेहतर की आवश्यकता है, तो this suggestion to use Mach's timing functions पर विचार करें। तो, NSDate का उपयोग कर, अपने कोड कुछ इस तरह हो सकता है:

- (IBAction)startStopwatch:(id)sender 
{ 
    self.startTime = [NSDate date]; 
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 
                target:self 
               selector:@selector(tick:) 
               userInfo:repeats:YES]; 
} 

- (void)tick:(NSTimer*)theTimer 
{ 
    self.elapsedTime = [self.startTime timeIntervalSinceNow]; 
    [self updateDisplay]; 
} 

- (IBAction)stopStopwatch:(id)sender 
{ 
    [self.timer invalidate]; 
    self.timer = nil; 
    self.elapsedTime = [self.startTime timeIntervalSinceNow]; 
    [self updateDisplay]; 
} 

आपका कोड एक छोटे से अधिक परिष्कृत हो सकता है अगर आप, को पुन: प्रारंभ करने की अनुमति देते आदि, लेकिन यहां महत्वपूर्ण बात यह है कि आप करने के लिए NSTimer उपयोग नहीं कर रहे है कुल विलुप्त समय मापें।

आपको this SO thread में अतिरिक्त सहायक जानकारी मिल जाएगी।

2

मैं इस समस्या के लिए केवीओ के खिलाफ सिफारिश करता हूं। यह यहां थोड़ा लाभ के लिए बहुत जटिलता (और कई कष्टप्रद गॉटचास) पेश करता है। केवीओ उन मामलों में महत्वपूर्ण है जहां आपको बिल्कुल न्यूनतम ओवरहेड सुनिश्चित करने की आवश्यकता है। ऐप्पल परतों जैसे निम्न-स्तर, उच्च प्रदर्शन वाली वस्तुओं के मामलों में इसका बहुत उपयोग करता है। यह एकमात्र आम तौर पर उपलब्ध समाधान है जो शून्य पर्यवेक्षक प्रदान करता है जब कोई पर्यवेक्षक नहीं होता है। ज्यादातर समय, आपको इसकी आवश्यकता नहीं है। केवीओ को सही तरीके से संभालना मुश्किल हो सकता है, और जो बग इसे बना सकते हैं, वे ट्रैक करने के लिए परेशान हैं।

आपके प्रतिनिधि दृष्टिकोण के साथ कुछ भी गलत नहीं है। यह सही एमवीसी है। वास्तव में चिंता करने की आवश्यकता केवल एक चीज यह है कि एनएसटीमर जब इसे बुलाया जाता है तो उसके बारे में मजबूत वादे नहीं करता है। एक दोहराने वाले टाइमर को कुछ मामलों में छोड़ने की भी अनुमति है। उस समस्या से बचने के लिए, आप आम तौर पर इसे बढ़ाने के बजाय वर्तमान समय के आधार पर elapsedTime की गणना करना चाहते हैं। यदि टाइमर रोक सकता है, तो आपको एक संचयक और "आखिरी बार कब शुरू हुआ" तिथि रखने की आवश्यकता है।

यदि आपको उच्च-सटीकता या कम लागत वाले टाइमर की आवश्यकता है, तो आप dispatch_source_set_timer() पर देख सकते हैं, लेकिन एक साधारण मानव-लक्षित स्टॉपवॉच के लिए, NSTimer ठीक है, और एक साधारण परियोजना के लिए एक उत्कृष्ट विकल्प है।

+0

मुझे छोड़ने वाले टाइमर और वृद्धि के उपयोग की समस्या से अवगत है। मैं NSDate का उपयोग कर रहा हूं और setElapsedTime में मैं NSDates की तुलना करता हूं (+ ऑफ़सेट होने पर ऑफ़सेट होने पर ऑफसेट) – Jach0

+0

मैं स्टॉपवॉच से प्राप्त एक अंतराल उलटी गिनती टाइमर को कार्यान्वित करने की कोशिश कर रहा हूं और इसमें कुछ अतिरिक्त विशेषताओं हैं जिनमें इंटरवर्वल और बाकी इंटरवल शामिल हैं, लेकिन लेबल मेरा ViewController थोड़ा अजीब अद्यतन किया गया है। मैंने सोचा कि इसे व्यू कंट्रोलर के टिक, टाइमर टिक और इंटरवल टाइमर टिक के बीच अनुक्रमिक कॉल के साथ कुछ करना पड़ सकता है। – Jach0

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