noway - PUBLIC
  • DOCS FOR THINGS
  • _ref
    • Working Memory
    • NASA’s 10 rules for writing mission-critical code
    • React Native
  • _docs
    • Cryptography
    • Store APIs Key in FrontEnd SDK issues
    • APIs abuse issues
    • Webpack
    • Specific things
      • Text recognition
    • Book reviews
      • April 2020
      • 1-2/2020
      • March 2020
    • Visualization
    • MacOS
    • Go
    • Server
      • Easy way to setup a local HTTP Server on macOS
    • React
    • Reading
    • Tips
      • MVP
      • Sleeping in the right way
      • Get more things done
    • VS Code
      • Intelligent doesn't auto complete the JSX attribute or react-native components
      • Setting.json
    • Service Registration
      • Apple Enterprise Developer Account
    • DevOps
      • Using NGINX for ReactJS
    • Firebase
      • Upload image
      • Save data
      • Save Data with unique key
      • Setup local firebase functions
    • Documentation
      • API Documentation
    • React Native
      • Tips
      • Performance
      • Patterns in React
      • Rendering in React
      • View JS from apk
      • Flatlist with large data list causes blank view
      • Facebook SDK
      • Screen Events
      • Hotkeys
      • Deep Links
        • iOS Deep Link: Universal Link vs URL Schemes‌
        • Deferred Link‌
      • Text going off screen with flexDirection: 'row'
  • _posts
    • 2020-07-13-How-to-Understand-things
    • 2019-02-20-how-to-create-Jekyll-blog-with-github-page
    • 2019-03-01-books-02-19
    • 2019-02-11-highlight-the-pragmatic-programmer-part-01
    • 2019-02-15-highlight-the-pragmatic-programmer-part-03
    • 2019-02-14-highlight-the-pragmatic-programmer-part-02
    • 2019-04-11-books-03-19
    • 2019-03-07-telegram-bot-as-a-real-time-logger
    • 2019-02-04-generic-loading-ios
    • 2019-01-31-summary-books-01-19
    • 2019-03-27-short-polling-with-Swift
    • 2019-02-22-try-catch-exception-rather-than-return-codes
    • 2019-09-29-api-docs
  • category-archive
  • tag-archive
Powered by GitBook
On this page
  • 1. Protocol for Pollingable item
  • 2. Polling Center
  • Singleton center
  • Queue for timer
  • Timer for each Pollingable item
  • Resume/Pause Pollingable items via polling uid
  • Add Pollingable item to Polling Center
  • Enable/Disable Pollingable item

Was this helpful?

  1. _posts

2019-03-27-short-polling-with-Swift

Previous2019-01-31-summary-books-01-19Next2019-02-22-try-catch-exception-rather-than-return-codes

Last updated 5 years ago

Was this helpful?

Repeating tasks, e.g. fetching APIs, are tasks/block codes need to be excuted every interval time. I sometimes have to deal with them. And they sometimes become massive with a lot of timer and release timer things. So I decide to write a simple short-polling center in Swift.

What I need a polling center do

  • Excute a task every interval

  • Excute tasks in a single background queue

  • Easy to enable/disable a polling

  • Seperate each polling

What I will implement

  • Protocol for polling item. So I can create my own polling item easily.

    • Have uid so I can manage them

    • Can config time interval

    • Have a handler for excuting

  • Polling center. For managing polling item.

    • Singleton object

    • Have a queue for every tasks can excute in background queue

    • Have a timer for each Pollingable item

    • Enable/disable Pollingable item in a queue also

1. Protocol for Pollingable item

protocol Pollingable {
  // default uid for polling
  func uid() -> String
  static func uid() -> String
  // interval in second
  func interval() -> Int
  // invoke handler every interval
  func eventHandler() -> (() -> Void)
}
extension Pollingable where Self: NSObject {
  func uid() -> String {
    return String(describing: Self.self)
  }

  static func uid() -> String {
    return String(describing: Self.self)
  }
}

2. Polling Center

Singleton center

  private static var sharedInstance: PollingCenter = {
    let pollingCenter = PollingCenter()
    return pollingCenter
  }()

  static func shared() -> PollingCenter {
    return sharedInstance
  }

Queue for timer

  private let serialQueueChanging = DispatchQueue(label: "serialQueuePollingCenter")

Timer for each Pollingable item

  private func createTimer(polling: Pollingable) -> DispatchSourceTimer {
    let queue = DispatchQueue.global(qos: .background)
    let timer = DispatchSource.makeTimerSource(queue: queue)
    timer.schedule(deadline: .now(), repeating: .seconds(polling.interval()))
    timer.setEventHandler(handler: {
      polling.eventHandler()()
    })
    return timer
  }

I've almost done for creating center. Now I will add polling items and let them running in queue.

Resume/Pause Pollingable items via polling uid

  fileprivate func resumePolling(_ uid: String) {
    if let polling = self.pollings[uid], let state = self.pollingStates[uid] {
      if state == false {
        self.pollingStates[uid] = true
        polling.resume()
      }
    }
  }

  fileprivate func pausePolling(_ uid: String) {
    if let polling = self.pollings[uid], let state = self.pollingStates[uid] {
      if state == true {
        self.pollingStates[uid] = false
        polling.suspend()
      }
    }
  }

I make them private because they have to be executed in a queue, so they won't be conflicted each others.

Add Pollingable item to Polling Center

  func addPolling(_ polling: Pollingable) {
    // check if uid is added
    if pollings.index(forKey: polling.uid()) == nil {
      // create timer for polling item
      pollings[polling.uid()] = createTimer(polling: polling)
      // defaut disable
      pollingStates[polling.uid()] = false
    }
  }

Enable/Disable Pollingable item

  func enablePolling(_ uid: String) {
    self.serialQueueChanging.sync {
      self.resumePolling(uid)
    }
  }
  func disablePolling(_ uid: String) {
    self.serialQueueChanging.sync {
      self.pausePolling(uid)
    }
  }

Excute resume/pause Polling item in the queue so they won't be conficted.

Done. Now I can use this simple center:

let pollingCenter = PollingCenter.sharedInstance()
let printPolling = PrintPolling() // Pollingable item
pollingCenter.addPolling(printPolling)
pollingCenter.enablePolling(printPolling.uid()) // item's running now

Short-polling repo
Source code