禁用 NSViewRepresentable 重绘动画

Disable NSViewRepresentable redrawing animations

提问人:Jason1923 提问时间:9/22/2023 最后编辑:Ken WhiteJason1923 更新时间:9/22/2023 访问量:52

问:

我正在分支 Apple ScreenCaptureKit 示例项目,我注意到在重新绘制 NSView 时,NSViewRepresentable 预览有时会应用动画淡入淡出。我想删除这个淡入。我相信这是 SwiftUI 自动应用动画——如果我错了,请纠正我。

我在下面附上了一个视频示例:

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

以下是代码的一些相关部分:

// 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
                    }
                }
            }
    }
}

到目前为止,我已经尝试了各种交易的东西。我是 Swift 和 SwiftUI 的新手,所以如果这是微不足道的,我深表歉意。.animation(nil)

Swift SwiftUI NSView ScreenCaptureKit

评论

0赞 malhal 9/24/2023
不确定这是否是问题所在,但可表示结构中的 CALayer init 是错误的内存泄漏,请将其移动到 CaptureVideoPreview 内部
0赞 malhal 9/24/2023
此外,它在 SwiftUI 中不是,这让我感觉 ScreenCaptureKit 团队并不擅长 SwiftUI.taskTask {}

答: 暂无答案