I can't read a JSON response through an extension in Swift

Hello how are you? I hope you can help me, I have a big problem.

I just got my first job as an iOS developer and I’m adjusting new features to the project I’m in charge of.

Before I joined the project there was another developer in my place who started the project and he is now not in the project.

I have this code that works to open the front camera, on the screen it puts a mask that is used to tell the user to place his face in that mask that is actually a guide, take a selfie photo, save it on the device and take said photo to send to the server via ‘manager.sendSelfieToken(parameters: params, file: “selfie.png”)’ found in the ’ sendSelfieToken()’ function.

There is another driver that instead of taking a selfie, records a video. So my task is to capture the selfie. In the controller where the video is recorded take the following extension and with its function

extension SelfieTokenViewController: ServiceManagerDelegate{ func returnStringResponse(response: String){

Which, I think, works to read the response from the server and so the controller acts on it.

I attach the code of my controller ‘SelfieTokenViewController’:

override func viewDidLoad() {
super.viewDidLoad()

    if AVCaptureDevice.authorizationStatus(for: .video) == .authorized{
        self.setPlayer()
    }else{
        AVCaptureDevice.requestAccess(for: .video) { (granted:Bool) in
            if granted{
                self.performSelector(onMainThread: #selector(self.setPlayer), with: nil, waitUntilDone: false)
                
            }else{
                let message = "Para continuar el proceso necesitamos acceso a tu cámara. Otorga a Dicio la opción de acceder a tu cámara dentro de Configuración."
                self.performSelector(onMainThread: #selector(self.showAlert(message:)), with: message, waitUntilDone: false)
            }
        }
    }
    // crear observador en caso de que el usuario acepte los permisos en segundo plano
    observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main, using: { [unowned self] notification in
        if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
            self.performSelector(onMainThread: #selector(self.setPlayer), with: nil, waitUntilDone: false)
        } else {
            let message = "Para continuar el proceso necesitamos acceso a tu cámara. Otorga a Dicio la opción de acceder a tu cámara dentro de Configuración."
            self.performSelector(onMainThread: #selector(self.showAlert(message:)), with: message, waitUntilDone: false)
        }
    })
    
    // Configurar la sesión de captura
    captureSession = AVCaptureSession()
    captureSession?.sessionPreset = .photo
    
    // Buscar la cámara frontal
    frontCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)
    
    // Configurar la entrada de la cámara frontal
    if let frontCamera = frontCamera {
        do {
            let input = try AVCaptureDeviceInput(device: frontCamera)
            if captureSession?.canAddInput(input) == true {
                captureSession?.addInput(input)
            }
        } catch {
            print("Error al configurar la entrada de la cámara frontal: \(error.localizedDescription)")
        }
    }
    // Configurar la máscara de guía
    self.animacion?.isHidden = false
    self.maskImage?.image = UIImage(named: "face_green")
    
    // Configurar la vista previa de la cámara
    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
    previewLayer?.videoGravity = .resizeAspectFill
    previewLayer?.frame = view.layer.bounds
    view.layer.insertSublayer(previewLayer!, at: 0)
    
    // Comenzar la sesión de captura
    DispatchQueue.global(qos: .background).async {
        self.captureSession?.startRunning()
    }
    
}
@objc func nextScreen() {
    let descripcion = "{\\\"coincidencia\\\":true,\\\"speech\\\":true}"
    let jsonLifeCycle = Util.createLifeCycleJson(status: "OK", description: descripcion, step: "captura_video_token", stepEvent: "captura_video_token", nombreOtorgante: AppConfig.shared.nombreCorto, nombreCompleto:  AppConfig.shared.name, telefono: "", correo: "", bandera: "", finished:  false, typeId: AppConfig.shared.IDTypeName.lowercased())
    self.lifecycleRequest = jsonLifeCycle
    let manager = ServiceManager()
    manager.delegate = self
    DispatchQueue.global(qos: .background).async {
        manager.updateLifeCycle(parameters: jsonLifeCycle)
    }
    //      Update Score
    let parameters = ["createScore" : "true" as Any,
                      "uuid" : AppConfig.shared.uuid as Any,
                      "transaccion": AppConfig.shared.idTransaction as Any]
    
    manager.updateInfoScore(parameters: parameters)
    //      End Update Score
    self.blurView?.removeBlurFromView()
    self.activityIndicator?.stopAnimating()
    self.activityView?.isHidden = true
    self.performSegue(withIdentifier: "TerminarViewController", sender: self)
}

@objc func stopSelfie() {
    
    self.animacion?.isHidden = true
    self.maskImage?.image = UIImage(named: "face_yellow")
    self.session.stopRunning()
    blurView?.addBlurToView()
    
    if self.activityView == nil {
        activityView = UIView(frame: CGRect(x: (self.view.frame.width / 2) - 50, y: (self.view.frame.height / 2) - 50, width: 100, height: 100))
        activityView!.backgroundColor = UIColor(red:0 , green: 0, blue: 0, alpha: 0.8)
        activityView!.layer.cornerRadius = 4
        activityIndicator = UIActivityIndicatorView(frame: CGRect(x: (activityView!.frame.width / 2) - 15, y: (activityView!.frame.height / 2) - 15, width: 30, height: 30))
        if #available(iOS 13.0, *) {
            activityIndicator!.style = .large
            activityIndicator?.color = .white
        } else {
            activityIndicator?.style = .whiteLarge
        }
        activityView!.addSubview(activityIndicator!)
        self.view.addSubview(activityView!)
    }
    
    activityIndicator?.startAnimating()
    activityView?.isHidden = false
    self.view.isUserInteractionEnabled = false
    
    //consumir servicio
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
        DispatchQueue.global(qos: .background).async {
            self.idServicio = 1
            self.sendSelfieToken()
        }
    }
}

@objc func captureButtonTapped() {
    
    //        guard let captureSession = captureSession else { return }
    
    if intentosRealizados == 1 {
        if session.canAddOutput(self.photoOutput) {
            session.addOutput(self.photoOutput)
        }
    }
    
    let settings = AVCapturePhotoSettings()
    if let connection = photoOutput.connection(with: .video) {
        // Ajustar la orientación a vertical
        connection.videoOrientation = .portrait
    }
    
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let fileUrl = paths[0].appendingPathComponent("selfie.png")
    try? FileManager.default.removeItem(at: fileUrl)
    photoOutput.capturePhoto(with: settings, delegate: self)
    
    DispatchQueue.main.asyncAfter(deadline: .now() +  6.0){
        self.performSelector(onMainThread: #selector(self.stopSelfie), with: nil, waitUntilDone: false)
    }
    
}

// Función para capturar una foto
func sendSelfieToken(){
    
    var isPasaporte = "false"
    if AppConfig.shared.IDType == 2 {
        isPasaporte = "true"
    }
    let params = [
        [
            "key": "uuidUser",
            "value": AppConfig.shared.uuid as Any,
            "type": "text"
        ],
        [
            "key": "service_call",
            "value": "videotoken-embedding",
            "type": "text"
        ],
        [
            "key": "created",
            "value": "0",
            "type": "text"
        ],
        [
            "key": "expire",
            "value": "0",
            "type": "text"
        ],            [
            "key": "identificacion_pasaporte",
            "value": isPasaporte as Any,
            "type": "text"
        ],
        [
            "key": "originOS",
            "value": "ios_native",
            "type": "text"
        ]
        
    ] as [[String : Any]]
    manager.sendSelfieToken(parameters: params, file: "selfie.png")
    //        print("SE ENVIÓ LA SELFIE")
    
}

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    
    self.animacion?.isHidden = true
    blurView?.addBlurToView()
    if self.activityView == nil {
        activityView = UIView(frame: CGRect(x: (self.view.frame.width / 2) - 50, y: (self.view.frame.height / 2) - 50, width: 100, height: 100))
        activityView!.backgroundColor = UIColor(red:0 , green: 0, blue: 0, alpha: 0.8)
        activityView!.layer.cornerRadius = 4
        activityIndicator = UIActivityIndicatorView(frame: CGRect(x: (activityView!.frame.width / 2) - 15, y: (activityView!.frame.height / 2) - 15, width: 30, height: 30))
        if #available(iOS 13.0, *) {
            activityIndicator!.style = .large
            activityIndicator?.color = .white
        } else {
            activityIndicator?.style = .whiteLarge
        }
        activityView!.addSubview(activityIndicator!)
        self.view.addSubview(activityView!)
    }
    
    self.maskImage?.image = UIImage(named: "face_yellow")
    
    if let imageData = photo.fileDataRepresentation(), let image = UIImage(data: imageData) {
        
        let compressedData = image.jpegData(compressionQuality: 0.5)
        if let compressedImage = UIImage(data: compressedData ?? Data()){
            
            if let compressedData = compressImage(image: compressedImage, maxSizeInBytes: 1 * 1024 * 1024) {
                
                
                let rotatedImage = UIImage(data: compressedData)?.rotate(radians: .pi / 0.5)
                let pngData = rotatedImage?.jpegData(compressionQuality: 1.0)
                
                let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                let fileURL = documentDirectory.appendingPathComponent("selfie.png")
                if let data = pngData {
                    blurView?.addBlurToView()
                    activityIndicator?.startAnimating()
                    activityView?.isHidden = false
                    self.blurView?.addBlurToView()
                    self.view.isUserInteractionEnabled = false
                    do {
                        try data.write(to: fileURL)
                        print("Se guardó la imagen en: \(fileURL)")
                        activityIndicator?.startAnimating()
                        activityView?.isHidden = false
                        self.view.isUserInteractionEnabled = false
                        
                        
                    } catch {
                        
                        print("Error al guardar la imagen: \(error.localizedDescription)")
                    }
                }
            }
        }
        
    }
    
}

extension SelfieTokenViewController: ServiceManagerDelegate{
func returnStringResponse(response: String) {
self.performSelector(onMainThread: #selector(self.stopSelfie), with: nil, waitUntilDone: false)
print(response)
let responseV = VideoTokenResponse.init(JSONString: response)
AppConfig.shared.faceApi = responseV
if responseV?.liveness == “Vivo” && responseV?.match == true {

        var payload: [String: Any]?
        
        do {
            let data = response.data(using: .utf8)!
            let json = try JSONSerialization.jsonObject(with: data) as! Dictionary<String, Any>
            payload = json["payload"] as? [String: Any]
        }
        
        catch {
            print("json serialization error")
        }
        
        var payloadString = Util.json(from: payload as Any)
        payloadString = payloadString?.replacingOccurrences(of: "\"", with: "\\\"")
        payloadString = payloadString?.replacingOccurrences(of: "\\\\\"", with: "\\\"")
        payloadString = payloadString?.replacingOccurrences(of: "\\\"[", with: "[")
        payloadString = payloadString?.replacingOccurrences(of: "]\\\"", with: "]")
        self.createEventSuccess(paso: "Captura Video Token", status: 200, payload: payloadString!)
        self.performSelector(onMainThread: #selector(self.nextScreen), with: nil, waitUntilDone: false)
        
    } else if responseV!.status > 0 && responseV?.status != 200 {
        
        let payload = "\\\"" + (responseV?.message)! + "\\\""
        self.createEventSuccess(paso: "Captura Video Token", status: (responseV?.status)!, payload: payload)
        self.messageFail = (responseV?.message)!
        self.statusFail = (responseV?.status)!
        self.performSelector(onMainThread: #selector(self.showMessageError(message:)), with: responseV?.message, waitUntilDone: false)
    } else {
        let payload = "\\\"" + (responseV?.message)! + "\\\""
        self.createEventSuccess(paso: "Captura Video Token", status: (responseV?.status)!, payload: payload)
        self.messageFail = (responseV?.message)!
        self.statusFail = (responseV?.status)!
        self.performSelector(onMainThread: #selector(self.showMessageError(message:)), with: responseV?.message, waitUntilDone: false)
    }
    
}

func returnResponseOTP(response: String, status: Int) {
    var payload = ""
    let tokens = OTPToken.init(JSONString: response)
    if tokens != nil && tokens?.codes != nil && tokens!.codes!.count > 0{
        payload = "{\"codes\":" + (tokens?.codes!.toJSONString())! + "}"
        payload = payload.replacingOccurrences(of: "\"", with: "\\\"")
        self.createEventSuccess(paso: "OTP", status: status, payload: payload)
        //  self.tokenArray = tokens
        self.performSelector(onMainThread: #selector(self.captureButtonTapped), with: nil, waitUntilDone: false)
        //self.performSelector(onMainThread: #selector(self.showToken), with: nil, waitUntilDone: false)
    } else {
        payload = "\\\"" + (tokens?.message_client)! + "\\\""
        self.createEventSuccess(paso: "OTP", status: status, payload: payload)
        let mensaje = "Por favor ubica tu rostro en el área marcada para continuar."
        self.performSelector(onMainThread: #selector(self.errorOnOTP(message:)), with: mensaje, waitUntilDone: false)
    }
}

func returnLifeCycleResponse(response: String, status: Int) {
    self.statusResponse = status
    self.createEventLifeCycle()
}

func error() {
    let mensaje = "No ha sido posible ubicar tu rostro o se perdió la conexión."
    self.performSelector(onMainThread: #selector(self.errorOnOTP(message:)), with: mensaje, waitUntilDone: false)
    
}

}

extension SelfieTokenViewController: AVCaptureVideoDataOutputSampleBufferDelegate {//AVCaptureVideoDataOutputSampleBufferDelegate {

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection){
    
    if getFrame{
        DispatchQueue.main.async { [unowned self] in
            guard let outputImage = self.imageFromSampleBuffer(sampleBuffer: sampleBuffer) else { return }
            let rotatedImage = outputImage.rotate(radians: .pi * 0.5)
            self.saveImageInSB(image: rotatedImage)
            
        }
        getFrame = false
    }
    
}

}

I hope to have your help, I thank you in advance!
Greetings.

Read the response from the server after the file has been sent and act on the response.

What is the specific problem you have? You posted that you have a problem, stated what you are trying to do, and showed a bunch of code, but you never said what the problem was.

What do you expect to happen? What happens?

By the way, there is a problem with the code blocks you inserted in your post. The start of your extensions are not formatted as code blocks, making the code hard to read.

1 Like

This topic was automatically closed after 166 days. New replies are no longer allowed.