0

这实际上与这篇文章AVCapturePhotoCaptureDelegate photoOutput() 不是每次都调用但没有人回应的问题相同。我发现在 takePic 上有时会调用 photoOutput 函数,而不是其他函数,它实际上是 50/50 。我正在使用 Swiftui 2.0 。有谁知道解决这个问题或为什么会发生这个问题?复制它的代码实际上很小。它是下面的代码,然后在info.plist 中设置隐私-相机使用说明和隐私-照片库使用说明的权限。我尝试了不同的方法,但实际上是否调用 photoOutput 仍然是 50/50。当它未被调用时,您将在日志中看到它print("Nil on SavePic:picData")任何建议都会很棒。

import SwiftUI
import AVFoundation

struct CreateStoryView: View {
    @StateObject var camera = CameraModel()
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
      
        ZStack {
            // Going to be Camera Preview
           CameraPreview(camera: camera)
                .ignoresSafeArea(.all, edges: .all)
            VStack {
                HStack {
                    Spacer()
                    Image(systemName: "arrowshape.turn.up.backward.circle.fill")
                        .foregroundColor(.black)
                        .padding(.trailing,20)
                        .background(Color.white)
                        .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
                        .onTapGesture {
                            if camera.session.isRunning == true {
                                camera.session.stopRunning()
                          
                            }
                            self.presentationMode.wrappedValue.dismiss()
                        }
                if camera.isTaken {
               
                        Button(action: camera.reTake, label: { // camera.reTake
                    Image(systemName: "arrow.triangle.2.circlepath.camera")
                        .foregroundColor(.black)
                        .padding()
                        .background(Color.white)
                        .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
                    })
                    .padding(.trailing,10)
                    }
                }
                
                Spacer()
                HStack{
                   // If Taken then showing save and again take button
                    if camera.isTaken{
                        Button(action: {if !camera.isSaved{camera.savePic()}}, label: {
                            Text(camera.isSaved ? "Saved" : "Save")
                            .foregroundColor(.black)
                            .fontWeight(.semibold)
                            .padding(.vertical,10)
                            .padding(.horizontal,20)
                            .background(Color.white)
                            .clipShape(Capsule())
                        })
                        .padding(.leading)
                        Spacer()
                        
                    } else {
                        Button(action: camera.takePic , label: {
                            ZStack{
                                Circle()
                                    .fill(Color.white)
                                    .frame(width: 65, height: 65)
                                
                                Circle()
                                    .stroke(Color.white,lineWidth: 2)
                                    .frame(width: 75, height: 75)
                            }
                        })
                    }
                }.frame(height: 75)
            }
        }.onAppear(perform: {
            camera.Check()
        })
    }
}

// Camera Model

class CameraModel: NSObject,ObservableObject,AVCapturePhotoCaptureDelegate {
    @Published var isTaken = false
    @Published var session = AVCaptureSession()
    @Published var alert = false
    @Published var output = AVCapturePhotoOutput()
    // preview ...
    @Published var preview: AVCaptureVideoPreviewLayer!
    @Published var isSaved = false
    @Published var picData = Data(count: 0)
    func Check() {
    // first checking camera has permission
        
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            setUp()
            return
        case .notDetermined:
            //retrusting for permission
        
            AVCaptureDevice.requestAccess(for: .video) {(status) in
                
                if status{
                    self.setUp()
                }
                
            }
        case .denied:
            self.alert.toggle()
            return
        default:
            return
        }
        
    }
    func setUp() {
        // setting up camera
        
        do{
            // setting configs...
            self.session.beginConfiguration()
            
            // change for your own
            
            let device = AVCaptureDevice.default(.builtInDualCamera,for: .video,position: .back)
            
            let input = try AVCaptureDeviceInput(device: device!)
            // checking and adding session
            if self.session.canAddInput(input) {
                self.session.addInput(input)
            }
            // same for output
            if (self.session.canAddOutput(self.output)) {
                self.session.addOutput(self.output)
            }
    
            self.session.commitConfiguration()
        } catch {
            print(error.localizedDescription)
        }
    }
    // take and retake
    func takePic(){
        DispatchQueue.global(qos: .background).async {

            self.output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
            self.session.stopRunning()
            DispatchQueue.main.async {
                withAnimation{ self.isTaken.toggle() }
        }
       }
    }
    
    func reTake() {
        DispatchQueue.global(qos: .background).async {
            self.session.startRunning()
            DispatchQueue.main.async {
              //  withAnimation{ self.isTaken.toggle() }
                // clearing
                //self.isSaved = false
                self.isTaken = false
        }
        }
    }
    
    
    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        print("photoOutput check")
        if error != nil {
            return
        }
        guard var imageData = photo.fileDataRepresentation() else {return}
        self.picData = imageData
        if isSaved == true {
        if !imageData.isEmpty {
           imageData.removeAll()
            isSaved = false
        }
        } else {
            isSaved = true
        }
        
    }
    func savePic() {
        if UIImage(data: self.picData) == nil {
            print("Nil on SavePic:picData")
            return
        }
        let image = UIImage(data: self.picData)!
        
        // saving image
        UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveError), nil)
        self.isSaved = true
        print("saved sucessfully")
    }
    
    @objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
            print("Save finished!")
        }
}

// setting up view for preview

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
        camera.preview.videoGravity = .resizeAspectFill
        view.layer.addSublayer(camera.preview)
        camera.session.startRunning()
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        
    }
}




struct CreateStoryView_Previews: PreviewProvider {
    static var previews: some View {
        CreateStoryView()
    }
}
4

0 回答 0