ios स्विफ्ट में सरल सेवा, बनी रहती है, केवल अग्रभूमि?




service swift3 (2)

मैं बस कुछ करना चाहता हूँ चलाने के लिए

  • हर 20 सेकंड का कहना है
  • बस केवल जब ऐप अग्रभूमि होता है (स्पष्ट रूप से जब पृष्ठभूमि नहीं चला जाता है)
  • जाहिर है, यह अधिक सुरुचिपूर्ण होगा यदि आपको ऐप के बाद और अग्रभूमि से बाहर जाने के बाद परेशान नहीं करना पड़ता है
  • मुद्दा, मुझे scheduleRepeating साथ सीखने के लिए आश्चर्य हुआ था कि पुन: प्रस्तुत करने से , सिम्युलेटर में, यह तब चलता रहता है जब ऐप पृष्ठभूमि में होता है: मुझे यह आश्वासन नहीं देता कि यह स्पष्ट रूप से पृष्ठभूमि में नहीं चला जाएगा (कुछ? जो भी?) डिवाइस
  • मुद्दा, मुझे पता चला कि डिवाइस पर, जितने पीढ़ियों / ओएस को संभव हो, scheduleRepeating साथ परीक्षण, परेशान करने के लिए (कुछ? सभी मामलों में) पुनरावृत्ति करना एक बार केवल तब होता है जब एप पृष्ठभूमि में जाता है इसका अर्थ यह है कि जब ऐप पृष्ठभूमि पर जाता है तो यह "एक बार" चलाता है चूसो।

तो दोहराएं: आईओएस में हर 20 सेकंड तक चलने वाली एक साधारण सेवा कैसे होती है, और केवल तब ही चलती है जब एप अग्रभूमि में होता है, और, यह फंस-मुक्त है .. आदर्श रूप से आपको इसे पुनः आरंभ करने की आवश्यकता नहीं है, जांचें एप के जीवन के दौरान यह या कुछ भी ...

वास्तव में ऐसा सरल काम करने का सबसे अच्छा तरीका क्या है?

यह मेरा (प्रतीत होता है) काम का समाधान है, जो कि असंगत है। निश्चित रूप से आईओएस में ऐसी स्पष्ट बात करने के लिए एक अंतर्निहित तरीके, या कुछ और है ??

open class SomeDaemon {

    static let shared = SomeDaemon()
    fileprivate init() { print("SomeDaemon is running") }
    var timer: DispatchSourceTimer? = nil
    let gap = 10   // seconds between runs

    func launch() {

        // you must call this from application#didLaunch
        // harmless if you accidentally call more than once
        // you DO NOT do ANYTHING on app pause/unpause/etc

        if timer != nil {

            print("SomeDaemon, timer running already")
            return
        }

        timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
        timer?.scheduleRepeating(deadline: .now(), interval: .seconds(gap))
        timer?.setEventHandler{ self. doSomeThing() }
        timer?.resume()
    }

    private func doSomeThing() {

        if UIApplication.shared.applicationState != .active {

            print("avoided infuriating 'runs once more in bg' problem.")
            return
        }

        // actually do your thing here
    }
}

https://code.i-harness.com


परदे के पीछे:

यह भव्य नहीं है, लेकिन यह बहुत अच्छी तरह से झकना काम करता है।

struct ForegroundTimer {
    static var sharedTimerDelegate: ForegroundTimerDelegate?
    static var sharedTimer = Timer()

    private var timeInterval: Double = 20.0

    static func startTimer() {
        ForegroundTimer.waitingTimer.invalidate()

        var wait = 0.0
        if let time = ForegroundTimer.startedTime {
            wait = timeInterval - (Date().timeIntervalSince1970 - time).truncatingRemainder(dividingBy: Int(timeInterval))
        } else {
            ForegroundTimer.startedTime = Date().timeIntervalSince1970
        }
        waitingTimer = Timer.scheduledTimer(withTimeInterval: wait, repeats: false) { (timer) in
            ForegroundTimer.sharedTimerDelegate?.timeDidPass()
            ForegroundTimer.sharedTimer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true, block: { (timer) in
                ForegroundTimer.sharedTimerDelegate?.timeDidPass()
            })
        }
    }

    static func pauseTimer() {
        ForegroundTimer.sharedTimer.invalidate()
    }

    private static var startedTime: TimeInterval?
    private static var waitingTimer = Timer()
}

protocol ForegroundTimerDelegate {
    func timeDidPass()
}

उपर्युक्त यह कोड उपयोग के लिए तैयार है जैसा है बेशक आप समय के अंतराल जो भी समय अंतराल कर सकते हैं आप चाहते हैं।

उपयोग सरल है:

AppDelegate.swift में, इन दो विधियों को रखें:

func applicationDidBecomeActive(_ application: UIApplication) {
    ForegroundTimer.startTimer()
}

func applicationDidEnterBackground(_ application: UIApplication) {
    ForegroundTimer.pauseTimer()
}

उसके बाद, जिस श्रेणी को आप 'सुनें' चाहते हैं, उसके लिए टाइमर को timeDidPass() लागू करना है, और इसकी आवश्यक पद्धति, timeDidPass() । अंत में, उस कक्षा / self को ForegroundTimer.sharedTimerDelegateForegroundTimer.sharedTimerDelegate उदाहरण के लिए:

class ViewController: UIViewController, ForegroundTimerDelegate {
    func viewDidLoad() {
        ForegroundTimer.sharedTimerDelegate = self
    }

    func timeDidPass() {
        print("20 in-foreground seconds passed")
    }
}

उम्मीद है की यह मदद करेगा!


@ डोपैप का उत्तर बहुत ही ठोस है और मैं इसके साथ जाना चाहता हूं, लेकिन अगर आप चाहते हैं कि यह भी आसान हो तो आप RunLoop के साथ कुछ कोशिश कर सकते हैं:

let timer = Timer.scheduledTimer(withTimeInterval: wait, repeats: true) { _ in print("time passed") }
RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)

यह आपको पृष्ठभूमि निष्पादन के बारे में कुछ कार्यात्मकता भी देगा।

चेतावनी: कोड का परीक्षण नहीं किया गया!





swift3