How to properly link CADisplayLink with SwiftUI?

Viewed 568

I am creating some animation and for smoothness on various devices I use CADisplayLink like this:

// DisplayLink.swift
import SwiftUI

class DisplayLink: NSObject, ObservableObject {
    @Published var frameDuration: CFTimeInterval = 0
    @Published var frameChange: Bool = false
    
    static let sharedInstance: DisplayLink = DisplayLink()
    
    func createDisplayLink() {
        let displaylink = CADisplayLink(target: self, selector: #selector(frame))
        displaylink.add(to: .current, forMode: RunLoop.Mode.default)
    }
    
    @objc func frame(displaylink: CADisplayLink) {
        frameDuration = displaylink.targetTimestamp - displaylink.timestamp
        frameChange.toggle()
    }
    
}

Then I initialize it once in the application:

// App.swift
import SwiftUI

@main
struct App: App {
    init() {
        DisplayLink.sharedInstance.createDisplayLink()
    }
    var body: some Scene {
        WindowGroup {
            CircleView()
        }
    }
}

And I use it throughout the application as follows:

// CircleView.swift
import SwiftUI

struct CircleView: View {
    @ObservedObject var displayLink = DisplayLink.sharedInstance
    //
    var body: some View {
       // 
       .onChange(of: displayLink.frameChange) { _ in
              print(displayLink.frameDuration)
           }
    }
    

Everything works great, but how correct is it to use this approach? Perhaps SwiftUI has ready-made methods for this?

0 Answers
Related