swift - 使用 AVFoundation 旋转 UIViewRepresentable View

标签 swift swiftui avfoundation uiviewcontrollerrepresentable

我使用 CameraPreview (UIViewRepresentable) 作为 UIKitSwiftUI 之间的桥梁。 CameraPreview 使用 CameraModel 配置并使用 AVCaptureVideoPreviewLayerCameraModel 正在配置 AVCaptureSessionAVCaptureDeviceInput。一切正常,除了当我尝试在 iPad 上旋转设备时除外。 CameraPreview 未正确旋转并使用之前旋转的输入。 (下图)我可以在 SwiftUI ( based on this article ) 中检查正在旋转的设备,但我不知道如何重新配置​​ CameraPreviewAVCaptureVideoPreviewLayer 的旋转。在我发现设备旋转后,有什么想法如何在 UIKit 中触发布局更新吗?

代码如下:

struct CameraView: View {
    @StateObject var camera = CameraModel()

    var body: some View {
            CameraPreview(camera: camera)
                .ignoresSafeArea(.all, edges: .all)
     }
}

struct CameraPreview: UIViewRepresentable {
    @ObservedObject var camera: CameraModel
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: UIScreen.main.bounds)
        camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
        camera.preview.frame = view.frame
        
        //your own properies
        camera.preview.videoGravity = .resizeAspectFill
        view.layer.addSublayer(camera.preview)
        
        //starting session
        camera.session.startRunning()
        return view
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) { }
}

class CameraModel: NSObject, ObservableObject, AVCapturePhotoCaptureDelegate {
    @Published var session = AVCaptureSession()
    @Published var preview: AVCaptureVideoPreviewLayer!
    @Published var output = AVCapturePhotoOutput()

    func setUp() {
        do {
            self.session.beginConfiguration()
            let device = AVCaptureDevice.default(for: .video)
            let input = try AVCaptureDeviceInput(device:device!)
            if self.session.canAddInput(input) {
                self.session.addInput(input)
            } 
            if self.session.canAddOutput(self.output) {
                self.session.addOutput(self.output)
            } 
            self.session.commitConfiguration()
            
        }catch {
            print(error.localizedDescription)
        }
    }
}

picture before rotation picture after rotation

最佳答案

我通过以下方式解决了这个问题:

  1. 使预览框架适应边界而不是框架

  2. 当我检测到某些 super View View 上的设备方向发生变化时,我会更改 deviceRotation 变量的值,这会自动触发 updateUIView > 功能。

     struct CameraPreview: UIViewRepresentable {
       @ObservedObject var camera: CameraModel
       var deviceRotation: UIDeviceOrientation
    
      func makeUIView(context: Context) -> UIView {
         let view = UIView(frame: UIScreen.main.bounds)
         camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
         camera.preview.frame = view.bounds
    
         //your own properies
         camera.preview.videoGravity = .resizeAspectFill
         view.layer.addSublayer(camera.preview)
    
         //starting session
         camera.session.startRunning()
         return view
      }
    
      func updateUIView(_ uiView: UIViewType, context: Context) {
         let view = UIView(frame: UIScreen.main.bounds)
         camera.preview.frame = view.bounds
      }  
    }
    
  3. 手动设置 AVCaptureConnection 上的 AVCaptureVideoOrientation 以正确的设备方向。每次当我检测到方向变化时我都会这样做:

    previewConnection.videoPreviewLayer?.connection?.videoOrientation = orientation.videoOrientation
    

关于swift - 使用 AVFoundation 旋转 UIViewRepresentable View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72186243/

相关文章:

ios - 当新用户使用 Swift 和 Parse 登录时,数据不会更新到当前用户

ios - 尝试使用几何阅读器和导航栏获得全宽 View - SwiftUI

ios - SwiftUI Picker 在通过 NavigationLink 显示时崩溃

ios - 对 body : Some View in ContentView in SwiftUI 奇怪的初始化语法感到好奇

swift - 在 AVAudioPlayer 中检测播放结束

objective-c - 尝试使用图层指令翻转视频时,AVFoundation AVAssetExportSession 会生成空白视频

swift - 如何动画 View 外观?

swift - 我怎样才能用阴影 View iOS swift 实现这种圆角半径?

ios - 如何将 URL 读入 AVURLAsset

ios - Swift 5 - 让 tableview 等到来自 api 调用的数据返回(使用多个 tableviews)