Search code examples
uikitmetal

Where should this render to MTKView while loop go in UIKit?


Regarding this tutorial...

It describes how to load frames from a video file and draw them one after another to a Metal view.

There is a while loop that iterates over each frame and calls draw on the view...

while sampleBuffer != nil {
    
    ...

    displayView.draw()

    ...
}

Where should this loop go? I have tried it in viewDidLoad and after a delay and lots of print outputs it only seems to show the final frame. It's as though you can't see updates to a view before viewDidLoad has finished.


Solution

  • I suppose I would put it in viewWillAppear(_:) or viewDidAppear(_:). However, this is the first time I've seen a draw command in a super tight loop like that, and it seems less than ideal.

    If you would like to control the draw manually, I would recommend the use of a CADisplayLink instead. The purpose of CADisplayLink is it is timed to be in sync with the system update of the screen. You can also set a preferred frame rate, which is nice.

    weak var displayLink: CADisplayLink?
    
    func createDisplayLink() {
        displayLink?.invalidate() // in case existing timer
        let displayLink = CADisplayLink(target: self, selector: #selector(update(_:)))
        displayLink.add(to: .main, forMode: .common) 
        displayLink.preferredFramesPerSecond = 30 // Optional set desired frame rate 
        self.displayLink = displayLink
    }
    
    @objc func update(_ displayLink: CADisplayLink) {
        displayView.draw()
    }
    
    func viewWillAppear(_ animated: Bool) {
        // You can create it earlier, but I prefer here 
        createDisplayLink() 
    }
    
    func viewWillDisappear(_ animated: Bool) {
        // Stop rending when view disappears
        displayLink?.invalidate()
    }