Jason1923
Jason1923

Reputation: 93

Disable NSViewRepresentable redrawing animations

I'm branching off of the Apple ScreenCaptureKit sample project and I noticed the NSViewRepresentable preview sometimes has a fade in animation applied when the NSView is redrawn. I would like to remove this fade in. I believe this is SwiftUI automatically applying an animation — please correct me if I am wrong.

I've attached a video example of this below:

https://github.com/jasonhan-vassar/switcher/assets/34594853/e9f6ad8e-4d3e-4e00-b7fa-b37b396fe3cf

Here are some relevant parts of the code:

// CapturePreview.swift
import SwiftUI

struct CapturePreview: NSViewRepresentable {

    // A layer that renders the video contents.
    private let contentLayer = CALayer()

    init() {
        contentLayer.contentsGravity = .resizeAspect
    }

    func makeNSView(context: Context) -> CaptureVideoPreview {
        CaptureVideoPreview(layer: contentLayer)
    }

    // The view isn't updatable. Updates to the layer's content are done in outputFrame(frame:).
    func updateNSView(_ nsView: CaptureVideoPreview, context: Context) {}

    // Called by ScreenRecorder as it receives new video frames.
    func updateFrame(_ frame: CapturedFrame) {
        contentLayer.contents = frame.surface
    }

    class CaptureVideoPreview: NSView {
        // Create the preview with the video layer as the backing layer.
        init(layer: CALayer) {
            super.init(frame: .zero)
            // Make this a layer-hosting view. First set the layer, then set wantsLayer to true.
            self.layer = layer
            wantsLayer = true
        }

        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
}
// ContentView.swift
import ScreenCaptureKit
import SwiftUI

struct ContentView: View {

    @State var isUnauthorized = false

    @StateObject var screenRecorder = ScreenRecorder()

    var body: some View {
        screenRecorder.capturePreview
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .aspectRatio(screenRecorder.contentSize, contentMode: .fit)
            .overlay {
                if isUnauthorized {
                    VStack {
                        Spacer()
                        Text("No screen recording permission.")
                            .font(.largeTitle)
                            .frame(maxWidth: .infinity)
                            .background(.red)

                    }
                }
            }
            .onAppear {
                Task {
                    if await screenRecorder.canRecord {
                        await screenRecorder.start()
                    } else {
                        isUnauthorized = true
                    }
                }
            }
    }
}

So far, I've tried .animation(nil) and various transaction stuff.
I'm new to Swift and SwiftUI, so apologies if this is trivial.

Upvotes: 1

Views: 116

Answers (0)

Related Questions