Как сделать вывод камеры той же переменной привязки, что и вывод PhotosPicker?

Я хочу, чтобы пользователи могли делать фотографии с помощью камеры или выбирать фотографию из своей библиотеки фотографий. Как только они выберут изображение, я хочу перевести их в режим редактирования с этим захваченным изображением. Библиотека фотографий работает отлично, потому что я могу идентифицировать выходные данные как захваченное изображение, а затем перенести эту фотографию в следующий просмотр. Я хочу сделать то же самое с выводом камеры... Как мне установить вывод камеры как «capturedImage», чтобы в режиме редактирования перемещалась только одна переменная фотографии (от CustomCameraView до UploadPostView)?

ЗагрузитьPostShell

      
import SwiftUI

struct UploadPostShell: View {
    @Environment(\.dismiss) private var dismiss
    @Binding var capturedImage: UIImage?
    @StateObject var viewModel = UploadPostViewModel()
    @StateObject var camera = CameraModel()

    var body: some View {
        VStack {
        HStack {
            Button {
                dismiss()
            } label: {
                HStack {
                    Image("xmark")
                        .renderingMode(.template)
                        .resizable()
                        .frame(width: 28, height: 28)
                        .foregroundColor(.white)
                    Spacer()
                }.frame(maxWidth: .infinity)
                    .padding(.leading, 8)
            }
            Spacer()
            
            VStack (alignment: .center) {
                Text("Add Post")
                    .font(Font.headline2)
                    .foregroundColor(.white)
            }.frame(maxWidth: .infinity)
            
            Spacer()
            
            VStack {
                Rectangle()
                    .frame(width: 28, height: 28)
                    .foregroundColor(.clear)
            }.frame(maxWidth: .infinity)
            
        }
        .frame(maxWidth: .infinity, maxHeight: 48)
        
        if let b = Binding($capturedImage) {
            UploadPostView(capturedImage: b, viewModel: viewModel)
        } else {
            CustomCameraView(capturedImage: $capturedImage)
        }
        
        HStack {
            Spacer()
            Button {
                //upload post logic here
                if let uiimage = capturedImage {
                    viewModel.uploadPost(caption: viewModel.caption, image: uiimage, rating: viewModel.rating, book: viewModel.book)
                    viewModel.loading = true
                }
            } label: {
                if viewModel.loading {
                    ProgressView()
                        .progressViewStyle(CircularProgressViewStyle(tint: .white))
                } else {
                    Image("send-fill")
                        .renderingMode(.template)
                        .resizable()
                }
            }
            .frame(width: 24, height: 24)
            .padding()
            .background(Color.accentColor)
            .foregroundColor(.white)
            .clipShape(Circle())
        }
        .padding(8)
    }
        .ignoresSafeArea(.keyboard, edges: .bottom)
        .background(.black)
        .onReceive(viewModel.$didUploadPost) { success in
            if success {
                dismiss()
                capturedImage = nil
            }
        }
    }
}

CustomCameraView

      import SwiftUI
import PhotosUI

struct CustomCameraView: View {
    @Environment(\.dismiss) private var dismiss
    @Binding var capturedImage: UIImage?
    @StateObject var camera = CameraModel()
    
    var body: some View {
        
        ZStack {
            
            GeometryReader { proxy in
                
                CameraView(camera: camera)
                
                if camera.isTaken == false {
                    VStack (alignment: .leading) {
                        
                        Spacer()
                        
                        HStack {
                            PhotoPicker { result in
                                switch result {
                                case .success(let image):
                                    capturedImage = image
                                case .failure(let error):
                                    print(error)
                                    capturedImage = nil
                                }
                            }
                            Spacer()
                            Button {
                                camera.takePic()
                            } label: {
                                Image(systemName: "circle")
                                    .font(.system(size: 72))
                                    .foregroundColor(.white)
                            }
                            Spacer()
                            Rectangle()
                                .foregroundColor(.clear)
                                .frame(width: 32, height: 28)
                        }
                        .padding()
                    }
                }
            }
            .padding(.horizontal, 4)
            .cornerRadius(6)
            .background(.black)
        }
        .onAppear {
            camera.checkPermissions()
        }
    }
}

Модель камеры

      
import Foundation
import AVFoundation
import SwiftUI

class CameraModel: NSObject, ObservableObject,AVCapturePhotoCaptureDelegate {
    @Published var isTaken = false
    
    @Published var session = AVCaptureSession()
    
    @Published var alert = false
    
    @Published var output = AVCapturePhotoOutput()
    
    @Published var preview = AVCaptureVideoPreviewLayer()
        
    @Published var picData = Data(count: 0)
        
    func checkPermissions() {
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { status in
                
                if status {
                    self.setupCamera()
                }
            }
        case .denied:
            return
        case .authorized:
            setupCamera()
            return
        default:
            return
        }
    }
    
    func setupCamera() {
        
        if let device = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: .back) {
            
            do {
                
                self.session.beginConfiguration()
                                
                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)
            }
        } else {
            
            print("camera not available")
            
        }
    }
    
    func takePic() {
        DispatchQueue.global(qos: .background).async {
            self.output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
            
            DispatchQueue.main.async {
                withAnimation{ self.isTaken.toggle() }
            }
        }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
          self.session.stopRunning()
        }
    }
    
    func reTake() {
        DispatchQueue.global(qos: .background).async {
            self.session.startRunning()
            
            DispatchQueue.main.async {
                withAnimation {
                    self.isTaken.toggle()
                }
            }
        }
    }
    
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        if error != nil {
            return
        }
        
        print("pic taken...")
        
        guard let imageData = photo.fileDataRepresentation() else { return }
        
        self.picData = imageData
    }
}

КамераView

      
import SwiftUI
import AVFoundation

struct CameraView: UIViewRepresentable {
    
    @ObservedObject var camera : CameraModel
    
    func makeUIView(context: Context) -> UIView {
        
        let view = UIView(frame: UIScreen.main.bounds)
        
        DispatchQueue.global().async {
            
            camera.session.startRunning()
            
            DispatchQueue.main.async {
                
                camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
                
                camera.preview.frame = view.frame
                
                camera.preview.videoGravity = .resizeAspectFill
                
                view.layer.addSublayer(camera.preview)
                
            }
            
        }
        
        return view
        
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        
    }
}

0 ответов

Другие вопросы по тегам