0

I have created a video recorder which works fine if I use it on a phone. Now I want to control it (open that view/camera and start/stop recording from the watch).

What I've did is I have created an ObservableObject and added a state for the .fullScreenCover which opens/hides camera.

I can open the camera from the watch by calling a function

  func sendCommand(_ command: ConnectivityCommands) {
    guard canSendToPeer() else { return }
    
    WCSession.default.sendMessage(["command" : command.rawValue],replyHandler: nil) { error in
      print("Cannot send message: \(String(describing: error))")
    }
  }

and receiving it:

  func session(
    _ session: WCSession,
    didReceiveMessage message: [String : Any]
  ) {
    
    if let cammandValue = message["command"] {
      guard let command = ConnectivityCommands(rawValue: cammandValue as! Int) else { return }
      
      DispatchQueue.main.async { [weak self] in
        switch command {
        case ConnectivityCommands.openPhoneCamera:
          self?.cameraOpen = true
        }
      }
    }

Main View that holds the camera view

  .fullScreenCover(isPresented: $connectivityManager.cameraOpen, content: {
    VideoRecorderView()
  })

WatchConnectivityManager

final class WatchConnectivityManager: NSObject, ObservableObject {
  
  static let shared = WatchConnectivityManager()
  @Published var cameraOpen: Bool = false // <<====

and View

import SwiftUI
import AVKit
import AVFoundation

struct VideoRecorderView: View {
  @EnvironmentObject private var assetsStoreVM: AssetsStoreViewModel
  @EnvironmentObject var connectivityManager: WatchConnectivityManager
  @StateObject var cameraVM: CameraViewModel = .init()
  @StateObject var stopWatch = StopWatch()
  
  private let fileManager = LocalFileManagerService.shared
  
  var body: some View {
      
      VStack {
        // camera output...
        
        HStack {
          if !cameraVM.isRecording {
            Button(action: {
              connectivityManager.cameraOpen = false
            }, label: {
              Image(systemName: "xmark").resizable().frame(width: 30, height: 30)
            })
          }
          
        }
        
        Spacer()
        
        Button(action: {
          if !cameraVM.isRecording {
            stopWatch.start()
            cameraVM.startRecording(completion: { (url, error) in
              assetsStoreVM.refreshAssets()
            })
          } else {
            stopWatch.stop()
            cameraVM.stopRecording()
          }
        }, label: {
          Image(systemName: cameraVM.isRecording ? "stop.circle" : "record.circle")
            .font(.system(size: 80))
            .foregroundColor(.red)
        })
        .padding()
      }.onDisappear {
        cameraVM.captureSession.stopRunning()
      }
  }
}

So now I would like to call a cameraVM.startRecording() from VideoRecorderView How to do it right?

breq
  • 24,412
  • 26
  • 65
  • 106

0 Answers0