You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中使用UIVideoEditorController的异常问题及解决方法咨询

解决SwiftUI中UIVideoEditorController代理不触发及全屏视图异常关闭问题

问题根源

  1. 代理方法不触发:你给UIVideoEditorController的videoPath赋值了source.absoluteString,但该属性要求传入本地文件的纯路径字符串(不带file://前缀),而absoluteString返回的是包含scheme的完整URL字符串,导致编辑器无法正确识别视频文件,后续代理回调自然无法触发。
  2. 全屏视图异常关闭:你使用了SwiftUI的@Environment(\.dismiss)来关闭视图,这个方法会直接操作SwiftUI的视图栈,而UIVideoEditorController本身是UIKit的模态导航控制器,二者的模态栈逻辑冲突,导致点击保存后连带关闭了上层的全屏覆盖视图。

修正方案

1. 修正VideoEditor实现

调整videoPath赋值逻辑,改用UIKit原生的dismiss方式,并实现完整的代理方法:

struct VideoEditor: UIViewControllerRepresentable {
    let source: URL
    let maxSeconds: TimeInterval
    let onSaved: (URL) -> Void
    let onCancel: () -> Void
    let onError: (Error) -> Void

    func makeUIViewController(context: Context) -> UIVideoEditorController {
        let editor = UIVideoEditorController()
        // 关键修正:使用本地文件纯路径,而非带scheme的absoluteString
        editor.videoPath = source.path
        editor.videoMaximumDuration = maxSeconds
        editor.videoQuality = .typeHigh
        editor.delegate = context.coordinator
        return editor
    }

    func updateUIViewController(_ uiViewController: UIVideoEditorController, context: Context) {}

    func makeCoordinator() -> Coordinator {
        Coordinator(
            onSaved: onSaved,
            onCancel: onCancel,
            onError: onError
        )
    }

    class Coordinator: NSObject, UINavigationControllerDelegate, UIVideoEditorControllerDelegate {
        private let onSaved: (URL) -> Void
        private let onCancel: () -> Void
        private let onError: (Error) -> Void

        init(onSaved: @escaping (URL) -> Void, onCancel: @escaping () -> Void, onError: @escaping (Error) -> Void) {
            self.onSaved = onSaved
            self.onCancel = onCancel
            self.onError = onError
        }

        func videoEditorController(_ editor: UIVideoEditorController, didSaveEditedVideoToPath editedVideoPath: String) {
            let url = URL(fileURLWithPath: editedVideoPath)
            // 让编辑器自己dismiss,完成后再回调SwiftUI
            editor.dismiss(animated: true) {
                self.onSaved(url)
            }
        }

        func videoEditorControllerDidCancel(_ editor: UIVideoEditorController) {
            editor.dismiss(animated: true) {
                self.onCancel()
            }
        }

        func videoEditorController(_ editor: UIVideoEditorController, didFailWithError error: Error) {
            editor.dismiss(animated: true) {
                self.onError(error)
            }
        }
    }
}

2. 调整ContentView的使用逻辑

在回调中手动更新SwiftUI的状态变量,确保视图状态同步:

struct ContentView: View {
    let videoToEdit: URL

    @State private var presentingFirstCover = false
    @State private var presentingEditor = false

    var body: some View {
        VStack {
            Button("Present first cover") {
                presentingFirstCover = true
            }
        }
        .fullScreenCover(isPresented: $presentingFirstCover) {
            VStack {
                Button("Present editor") {
                    presentingEditor = true
                }
            }
            .fullScreenCover(isPresented: $presentingEditor) {
                VideoEditor(
                    source: videoToEdit,
                    maxSeconds: 20,
                    onSaved: { url in
                        print("saved edited video to: \(url)")
                        presentingEditor = false
                    },
                    onCancel: {
                        presentingEditor = false
                    },
                    onError: { error in
                        print("edit error: \(error)")
                        presentingEditor = false
                    }
                )
                .ignoresSafeArea()
            }
        }
    }
}

关键说明

  • 用source.path替代absoluteString:确保UIVideoEditorController能正确读取本地视频文件,触发编辑流程和代理回调。
  • 让编辑器自行dismiss:通过editor.dismiss(animated:completion:)关闭UIKit模态控制器,避免干扰SwiftUI的视图栈,仅在回调中更新SwiftUI的状态变量,保持二者状态同步。
  • 实现完整代理方法:覆盖保存、取消、失败三种场景,避免未处理的异常导致视图状态混乱。

内容的提问来源于stack exchange,提问作者wristbands

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:29:58