Swiftui photoOutput для изображений не вызывается каждый раз

avatar
user1591668
9 августа 2021 в 04:27
122
0
0

На ​​самом деле это та же проблема, что и в этом сообщении AVCapturePhotoCaptureDelegate photoOutput() не вызывается каждый раз однако никто не ответил на это. Я обнаружил, что на takePic иногда вызывается функция photoOutput, а не другие, это буквально 50/50. Я использую Swiftu 2.0. Кто-нибудь знает, как обойти это или почему эта проблема возникает? Код для воспроизведения этого на самом деле довольно мал. Это код ниже, а затем установка разрешений в info.plist для Конфиденциальность — описание использования камеры и конфиденциальность — описание использования фотобиблиотеки. Я пробовал разные вещи, и это буквально 50/50 в зависимости от того, вызывается ли photoOutput . Когда он не вызывается, вы увидите это в журнале 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()
    }
}
Источник
aheze
9 августа 2021 в 04:29
0

Зачем фоткать на фоне темы? DispatchQueue.global(qos: .background).async {

user1591668
9 августа 2021 в 05:34
0

Я просто следовал примеру из этого видео youtu.be/8hvaniprctk . Было бы лучше взять это в основной поток?

aheze
9 августа 2021 в 05:35
0

определенно да

Sylar
2 ноября 2021 в 19:13
0

Я следую указанному учебнику. Каков ответ на это, пожалуйста?

Ответы (0)