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

如何在UIViewController与SwiftUI View间共享捕获的图片数据?

解决SwiftUI与UIKit拍照组件的图片传递问题

要把UIKit捕获的图片传到SwiftUI的ContentView,核心是通过Binding + 闭包实现跨框架的数据传递,具体修改如下:

1. 修改ContentView,添加状态变量存储捕获的图片

在ContentView里声明一个@State变量,用来接收从UIKit传来的图片:

import SwiftUI // 补充导入SwiftUI(原代码遗漏)
import AVFoundation
import UIKit

struct ContentView: View {
    // 新增:存储捕获的图片
    @State private var capturedImage: UIImage?
    
    var body: some View {
        ZStack {
            Color.purple
            
            // 将Binding传递给HostedViewController
            HostedViewController(capturedImage: $capturedImage)
                .ignoresSafeArea()
            
            // 可选:在ContentView中直接展示捕获的图片
            if let image = capturedImage {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()
                    .padding()
            }
        }
    }
}

#Preview {
    ContentView()
}

2. 修改HostedViewController,添加Binding属性

让UIViewControllerRepresentable接收ContentView传来的Binding,同时指定具体的ViewController类型(避免使用基类):

struct HostedViewController: UIViewControllerRepresentable {
    // 新增:接收ContentView的Binding
    @Binding var capturedImage: UIImage?
    
    func makeUIViewController(context: Context) -> ViewController {
        let vc = ViewController()
        // 设置闭包,用于接收ViewController传来的图片
        vc.onImageCaptured = { image in
            self.capturedImage = image
        }
        return vc
    }
    
    func updateUIViewController(_ uiViewController: ViewController, context: Context) {
    }
    
    // 修改为具体的ViewController类型
    typealias UIViewControllerType = ViewController
}

3. 在ViewController里添加闭包,用于传递图片

给ViewController添加一个可选闭包,当捕获到图片时触发它:

class ViewController: UIViewController {
    // capture session
    var session: AVCaptureSession?
    
    // photo output
    let output = AVCapturePhotoOutput()
    
    // video preview
    let previewLayer = AVCaptureVideoPreviewLayer()
    
    // 新增:闭包,向外部传递图片
    var onImageCaptured: ((UIImage) -> Void)?
    
    //The rest is a bunch of AVCapture stuff that isn't relevant to my question
    
    @objc private func didTapTakePhoto() {
        output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
    }
}

4. 修改photoOutput方法,调用闭包传递图片

在捕获到图片后,调用闭包把图片传给外部,可按需移除UIKit内的图片展示代码:

extension ViewController: AVCapturePhotoCaptureDelegate {
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        guard let data = photo.fileDataRepresentation(),
              let image = UIImage(data: data) else {
            return
        }

        // 调用闭包,将图片传递给ContentView
        onImageCaptured?(image)
        
        session?.stopRunning()
        
        // 可选:若不需要在UIKit界面展示图片,可删除以下代码
        // let imageView = UIImageView(image: image)
        // imageView.contentMode = .scaleAspectFill
        // imageView.frame = view.bounds
        // view.addSubview(imageView)
    }
}

修改完成后,拍照捕获的图片会通过闭包和Binding自动同步到ContentView的capturedImage变量中,你可以在SwiftUI视图里自由使用这张图片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:36:11