स्विफ्ट में हर एक्स मिनट में कुछ करें


113

मैं हर मिनट एक फ़ंक्शन कैसे चला सकता हूं? जावास्क्रिप्ट में मैं ऐसा कुछ कर सकता हूं setInterval, क्या स्विफ्ट में भी कुछ ऐसा ही है?

चाहता था उत्पादन:

हैलो वर्ल्ड एक मिनट ...


स्विफ्ट 2 के लिए अपडेट किया गया: स्विफ्ट टाइमर
जेम्सगैस

जवाबों:


171
var helloWorldTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("sayHello"), userInfo: nil, repeats: true)

func sayHello() 
{
    NSLog("hello World")
}

फाउंडेशन आयात करना याद रखें।

स्विफ्ट 4:

 var helloWorldTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(ViewController.sayHello), userInfo: nil, repeats: true)

 @objc func sayHello() 
 {
     NSLog("hello World")
 }

1
लेकिन क्या होगा यदि आप दृश्य के बीच स्विच करना चाहते हैं? कोड सही बंद हो जाएगा?
Cing

5
@Cing निर्भर करता है कि स्वयं का क्या जिक्र है।
अंटीज

1
यह मत भूलो कि NSTimerयह लक्ष्य बनाए रखता है, इसलिए, इस सेटअप के साथ, यदि आपके पास helloWorldTimerएक संपत्ति है , तो selfआप अपने आप को एक चक्र बनाए रखें, जहां selfबनाए रखता है helloWorldTimerऔर helloWorldTimerरखता है self
MANIAK_dobrii

@MANIAK_dobrii क्या आप यह भी बता सकते हैं कि चक्र को कैसे बनाए रखा जाए? अगर वीसी बर्खास्त कर दिया जाता है लेकिन टाइमर रद्द नहीं किया जाता है, तो चक्र अभी भी चातुर्य में है? तो आप दोनों को टाइमर को रद्द करना होगा और फिर चक्र को तोड़ने के लिए दृश्य को खारिज करना होगा?
डेव जी

1
स्विफ्ट 4 के लिए, जिस विधि से आप चयनकर्ता को प्राप्त करना चाहते हैं, वह ऑब्जेक्टिव-सी के संपर्क में होना चाहिए, इस प्रकार @objc विशेषता को विधि घोषणा में जोड़ा जाना चाहिए। जैसे `` `@objc func sayHello () {}` ``
शमीम हुसैन

136

यदि iOS संस्करण 10 और उससे अधिक को लक्षित किया जाता है, तो आप ब्लॉक-आधारित रेंडरिंग का उपयोग कर सकते हैं Timer, जो संभावित मजबूत संदर्भ चक्रों को सरल करता है, जैसे:

weak var timer: Timer?

func startTimer() {
    timer?.invalidate()   // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it
    timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
        // do something here
    }
}

func stopTimer() {
    timer?.invalidate()
}

// if appropriate, make sure to stop your timer in `deinit`

deinit {
    stopTimer()
}

जबकि Timerआम तौर पर सर्वोत्तम है, पूर्णता के लिए, मुझे ध्यान देना चाहिए कि आप डिस्पैच टाइमर का भी उपयोग कर सकते हैं, जो पृष्ठभूमि थ्रेड्स पर टाइमर शेड्यूल करने के लिए उपयोगी है। प्रेषण टाइमर के साथ, चूंकि वे ब्लॉक-आधारित हैं, इसलिए जब तक आप संदर्भ का उपयोग करते हैं, तब तक पुराने target/ selectorपैटर्न के साथ कुछ मजबूत संदर्भ चक्र चुनौतियों से बचते हैं ।Timerweak

इसलिए:

var timer: DispatchSourceTimer?

func startTimer() {
    let queue = DispatchQueue(label: "com.domain.app.timer")  // you can also use `DispatchQueue.main`, if you want
    timer = DispatchSource.makeTimerSource(queue: queue)
    timer!.schedule(deadline: .now(), repeating: .seconds(60))
    timer!.setEventHandler { [weak self] in
        // do whatever you want here
    }
    timer!.resume()
}

func stopTimer() {
    timer?.cancel()
    timer = nil
}

deinit {
    self.stopTimer()
}

अधिक जानकारी के लिए, कंसीडर प्रोग्रामिंग गाइड के डिस्पैच सोर्सेज सेक्शन में डिस्पैच सोर्स एग्जाम्पल्स का टाइमर सेक्शन बनाना देखें


स्विफ्ट 2 के लिए, इस उत्तर का पिछला संशोधन देखें ।


इस दृष्टिकोण के भीतर आप केवल एक ही समय में कैसे कार्यान्वित करेंगे?
जुआन बोएरो

@JuanPabloBoero - मैं एक बार आग की स्थिति के लिए इस दृष्टिकोण का उपयोग नहीं करूंगा। आप उपयोग करेंगे dispatch_after। या एक गैर-दोहराव NSTimer
रोब

@ मेरे पास स्क्रीन पर एक काउंटर लेबल है जो हर सेकंड एक फ़ंक्शन से अपडेट हो जाता है, और मैं अपने काउंटर को बढ़ाने के लिए और लेबल पाठ को अपडेट करने के लिए उपरोक्त कोड का उपयोग कर रहा हूं। लेकिन, मैं जिस मुद्दे का सामना कर रहा हूं, वह यह है कि मेरा काउंटर वेरिएबल हर सेकेंड में अपडेट हो जाता है, लेकिन स्क्रीन मेरे यूलेबेल में नवीनतम काउंटर वैल्यू नहीं दिखाता है।
नागेंद्र राव

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

1
यह प्रश्न इस उत्तर की टिप्पणियों में यहाँ नहीं है। ऊपर दी गई टिप्पणियों को हटाएं और अपना प्रश्न पोस्ट करें। लेकिन, संक्षेप में, आप आमतौर पर ऐप को पृष्ठभूमि में नहीं रखते हैं, लेकिन केवल इसे वैसा ही बनाते हैं जैसा कि यह था। Stackoverflow.com/a/31642036/1271826 देखें ।
राब

17

यहां NSTimerउत्तर के लिए एक अद्यतन है , स्विफ्ट 3 के लिए (जिसमें NSTimerनाम बदला गया था Timer) एक नामित फ़ंक्शन के बजाय एक क्लोजर का उपयोग करते हुए:

var timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) {
    (_) in
    print("Hello world")
}

6
यह केवल iOS 10 के लिए है।
ग्लेन

कृपया ios 10+ समाधान पोस्ट न करें
नुमान कारासलान

13

यदि आप कुछ समय के लिए बहाव कर सकते हैं, तो हर मिनट किसी न किसी कोड को निष्पादित करने का एक सरल उपाय है:

private func executeRepeatedly() {
    // put your code here

    DispatchQueue.main.asyncAfter(deadline: .now() + 60.0) { [weak self] in
        self?.executeRepeatedly()
    }
}

बस executeRepeatedly()एक बार चलाएं और इसे हर मिनट निष्पादित किया जाएगा। निष्पादन ऑब्जेक्ट बंद होने पर निष्पादन बंद हो जाता selfहै। आप एक झंडे का उपयोग यह इंगित करने के लिए भी कर सकते हैं कि निष्पादन बंद होना चाहिए।


यह निर्णय इन सभी टाइमर के आसपास होने की तुलना में अधिक सुविधाजनक है, उन्हें रन-अप में जोड़कर, उन्हें अमान्य ... कूल!
julia_v

यह मान्य समाधान लगता है, लेकिन यह एक चक्र बना रहा है जब मैं इसे अपने वेब सेवा कॉल के साथ उपयोग कर रहा हूं ...
jayant rawat

11

आप उपयोग कर सकते हैं Timer(स्विफ्ट 3)

var timer = Timer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("function"), userInfo: nil, repeats: true)

चयनकर्ता () में आप अपने फ़ंक्शन का नाम डालते हैं


आप इसे स्विफ्ट 3 में कैसे कर सकते हैं?
बिबसी 16

1
उपयोग Timer... NSTimerका नाम बदल दिया गया है
जोसेफ

7

स्विफ्ट 3.0 में जीसीडी रिफ्लेक्ट हो गया:

let timer : DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)

timer.scheduleRepeating(deadline: .now(), interval: .seconds(60))
timer.setEventHandler
{
    NSLog("Hello World")
}
timer.resume()

यह विशेष रूप से तब उपयोगी होता है जब आपको किसी विशेष कतार में भेजने की आवश्यकता होती है। इसके अलावा, यदि आप उपयोगकर्ता इंटरफ़ेस अपडेट के लिए इसका उपयोग करने की योजना बना रहे हैं, तो मेरा सुझाव है CADisplayLinkकि यह GPU रीफ्रेश दर के साथ सिंक्रनाइज़ है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.