Swiftgram/submodules/GraphCore/Sources/Helpers/DisplayLinkService.swift

82 lines
2.1 KiB
Swift

//
// DisplayLinkService.swift
// GraphTest
//
// Created by Andrei Salavei on 4/7/19.
// Copyright © 2019 Andrei Salavei. All rights reserved.
//
import Foundation
#if os(macOS)
import Cocoa
#else
import UIKit
#endif
import CoreGraphics
public protocol DisplayLinkListner: AnyObject {
func update(delta: TimeInterval)
}
// DispatchSource mares refreshes more accurate
class DisplayLinkService {
let listners = NSHashTable<AnyObject>.weakObjects()
static let shared = DisplayLinkService()
public func add(listner: DisplayLinkListner) {
listners.add(listner)
startDisplayLink()
}
public func remove(listner: DisplayLinkListner) {
listners.remove(listner)
if listners.count == 0 {
stopDisplayLink()
}
}
private init() {
dispatchSourceTimer.schedule(deadline: .now() + 1.0 / 60, repeating: 1.0 / 60)
dispatchSourceTimer.setEventHandler {
DispatchQueue.main.sync {
self.fire()
}
}
}
private var dispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: .global(qos: .userInteractive))
private var dispatchSourceTimerStarted: Bool = false
private var previousTickTime = 0.0
private func startDisplayLink() {
guard !dispatchSourceTimerStarted else { return }
dispatchSourceTimerStarted = true
previousTickTime = CACurrentMediaTime()
dispatchSourceTimer.resume()
}
private func stopDisplayLink() {
guard dispatchSourceTimerStarted else { return }
dispatchSourceTimerStarted = false
dispatchSourceTimer.suspend()
}
public func fire() {
let currentTime = CACurrentMediaTime()
let delta = currentTime - previousTickTime
previousTickTime = currentTime
let allListners = listners.allObjects
var hasListners = false
for listner in allListners {
(listner as! DisplayLinkListner).update(delta: delta)
hasListners = true
}
if !hasListners {
stopDisplayLink()
}
}
}