ios – Swift AVFoundation can’t publish updates while view updates


I have some code below that records videos using AVFoundation. When my app launches I get the warning “Publishing changes from within view updates is not allowed, this will cause undefined behavior” on the line “@StateObject var cameraModel = CameraViewModel()”. I tried debugging this but couldn’t find a way to get ride of it. Is this related to using @StateObject?

import SwiftUI
import SwiftUI
import AVKit
import AVFoundation

struct HomeStory: View {
  @StateObject var cameraModel = CameraViewModel()
  
  var body: some View {
      ZStack(alignment: .bottom) {
      }
  }
}

struct CameraPreview: UIViewRepresentable {
  @EnvironmentObject var cameraModel : CameraViewModel
  var size: CGSize
  
  func makeUIView(context: Context) ->  UIView {
      let view = UIView()
      
      cameraModel.preview = AVCaptureVideoPreviewLayer(session: cameraModel.session)
      cameraModel.preview.frame.size = size
      
      cameraModel.preview.videoGravity = .resizeAspectFill
      view.layer.addSublayer(cameraModel.preview)
      
      DispatchQueue.global(qos: .userInitiated).async {
          cameraModel.session.startRunning()
      }
      
      return view
  }
  
  func updateUIView(_ uiView: UIView, context: Context) { }
}


class CameraViewModel: NSObject, ObservableObject, AVCaptureFileOutputRecordingDelegate {
  @Published var session = AVCaptureSession()
  @Published var alert = false
  @Published var output = AVCaptureMovieFileOutput()
  @Published var preview : AVCaptureVideoPreviewLayer!
  @Published var isRecording: Bool = false
  @Published var recordedURLs: [URL] = []
  @Published var previewURL: URL?
  @Published var showPreview: Bool = false
  @Published var recordedDuration: CGFloat = 0
  @Published var maxDuration: CGFloat = 20
  
  func checkPermission(){
      
      switch AVCaptureDevice.authorizationStatus(for: .video) {
      case .authorized:
          setUp()
          return
      case .notDetermined:
          AVCaptureDevice.requestAccess(for: .video) { (status) in
              
              if status{
                  self.setUp()
              }
          }
      case .denied:
          self.alert.toggle()
          return
      default:
          return
      }
  }
  
  func setUp(){
      
      do{
          self.session.beginConfiguration()
          let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
          let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
          let audioDevice = AVCaptureDevice.default(for: .audio)
          let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
          
          // MARK: Audio Input
          
          if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
              self.session.addInput(videoInput)
              self.session.addInput(audioInput)
          }

          if self.session.canAddOutput(self.output){
              self.session.addOutput(self.output)
          }
          
          self.session.commitConfiguration()
      }
      catch {
          print(error.localizedDescription)
      }
  }
  
  func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {

  }
  
  func mergeVideos(assets: [AVURLAsset],completion: @escaping (_ exporter: AVAssetExportSession)->()) async {

  }
}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img