SwiftUI集成PKCanvasView出现屏幕闪烁及IOSurface分配失败问题
解决PKCanvasView在SwiftUI中IOSurface分配失败与屏幕闪烁问题
问题根源
你当前的实现直接将ViewModel中的PKCanvasView实例通过Binding传递给UIViewRepresentable,这违背了SwiftUI对UIViewRepresentable的生命周期管理规则——UIViewRepresentable应当自行创建和管理UIView实例,复用外部传入的实例会导致渲染资源(如IOSurface)分配冲突,进而引发日志报错和屏幕闪烁。
解决方案
1. 重构UIViewRepresentable,自行创建PKCanvasView
修改DrawingCanvasView,让它负责创建画布实例,并通过回调将实例传递给外部:
struct DrawingCanvasView: UIViewRepresentable { let drawingPolicy: PKCanvasViewDrawingPolicy let onCanvasCreated: (PKCanvasView) -> Void func makeUIView(context: Context) -> PKCanvasView { let canvas = PKCanvasView() canvas.drawingPolicy = drawingPolicy onCanvasCreated(canvas) return canvas } func updateUIView(_ uiView: PKCanvasView, context: Context) { // 可在此处根据需求同步视图状态 } }
2. 更新ContentView,通过回调获取画布实例
不再传递Binding类型的canvas,改为在视图创建时通过回调将实例赋值给ViewModel:
struct ExperienceDrawingContentView: View { @ObservedObject private var viewModel: ExperienceDrawingContentViewModel init(viewModel: ExperienceDrawingContentViewModel) { self.viewModel = viewModel } var body: some View { DrawingCanvasView(drawingPolicy: .anyInput, onCanvasCreated: { canvas in viewModel.canvas = canvas }) .onAppear(perform: viewModel.handleViewDidLoad) .navigationTitle("Draw") .toolbar { Button("Done") { viewModel.handleDone() } } } }
3. 优化ViewModel的画布属性
将ViewModel中的canvas改为可选类型,避免提前初始化空实例:
class ExperienceDrawingContentViewModel: ObservableObject { var canvas: PKCanvasView? // 改为可选类型 // 其他业务逻辑代码... }
4. 关闭Metal API Validation(调试优化)
在Xcode的Scheme设置中,进入Run -> Arguments -> Environment Variables,移除METAL_API_VALIDATION_ENABLED或设置其值为NO(发布版会自动关闭该验证)。
现象复现

内容的提问来源于stack exchange,提问作者Blacksmith
相关产品推荐
相关产品推荐

