Tengo un campo y un botón cuando llenas el campo con contenido y haces clic en el botón:

@IBAction func dpSomething(_ sender: UIButton) {
    activityIndicator.startAnimating()
    activityIndicator.isHidden = false
    field.isHidden = true
    send.isHidden = true
    let url = "http://urlwithjson"
    let session = URLSession.shared
    DispatchQueue.main.async { [unowned self] in
        let task = session.dataTask(with: URL(string: url)!) { (data, response, error) in
            if(error==nil){
                        do {
                            let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                                if((jsonData["response"] as! Int) == 0){
                                    self.responseL.text = "no results"
                                }
                            self.activityIndicator.stopAnimating()
                            self.responseL.isHidden = false
                        } catch _ {}
            }
        }
        task.resume()
    }

}

Cuando uso imprimir me imprime casi de inmediato el JSON, pero el indicador de actividad necesita de 10 a 20 segundos para desaparecer o, a veces, no desaparece. ¿Alguien puede decirme por qué? Y también cuando cambio el texto en la etiqueta, recibo un error en la consola:

Esta aplicación modifica el motor de diseño automático desde un hilo en segundo plano, lo que puede provocar daños en el motor y fallos extraños. Esto provocará una excepción en una versión futura.

¿Por qué está pasando esto?

1
Bogdan Bogdanov 15 dic. 2016 a las 17:55

2 respuestas

La mejor respuesta

En primer lugar, agregue el siguiente código después de activityIndicator.startAnimating(), este código ocultará los indicadores de actividad que llame self.activityIndicator.stopAnimating():

activityIndicator.hidesWhenStopped = true

Además, solo está ocultando el indicador de actividad si la respuesta tuvo éxito, por lo que es posible que deba ocultar el indicador cuando haya un error en el bloque de captura y en el bloque else cuando obtenga un error de la respuesta de la API

Otro punto es que cuando realiza su solicitud, se supone que no debe estar en el hilo principal, solo en segundo plano y luego, cuando necesite actualizar la interfaz de usuario, use el hilo principal, por lo que finalmente aquí está el código completo que puede necesitar:

 @IBAction func dpSomething(_ sender: UIButton) {
    activityIndicator.startAnimating()
    activityIndicator.isHidden = false
    activityIndicator.hidesWhenStopped = true
    field.isHidden = true
    send.isHidden = true
    let url = "http://urlwithjson"
    let session = URLSession.shared
    let task = session.dataTask(with: URL(string: url)!) { (data, response, error) in
            if(error==nil){
                do {
                    let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                    if((jsonData["response"] as! Int) == 0){
                        DispatchQueue.main.async {
                        //Update your UI here


                         self.responseL.text = "no results"
                        }
               }

                    DispatchQueue.main.async {
                        //Update your UI here
                        self.activityIndicator.stopAnimating()
                        self.responseL.isHidden = false
                    }

                } catch _ {

                    // JSONSerialization error might happen so hide the indicator
                    DispatchQueue.main.async {
                        //Update your UI here
                        self.activityIndicator.stopAnimating()
                        self.responseL.isHidden = false
                    }

                }
            }else {
                // api response error might happen so hide the indicator
                DispatchQueue.main.async {
                    //Update your UI here
                    self.activityIndicator.stopAnimating()
                    self.responseL.isHidden = false
                }

            }
        }
        task.resume()

}
4
AaoIi 15 dic. 2016 a las 15:24

Solo necesita hacer UI cambios en el hilo main nunca llamar a la API Async en el hilo principal.

    let task = session.dataTask(with: URL(string: url)!) { (data, response, error) in
        if(error==nil){
                    do {
                        let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                            if((jsonData["response"] as! Int) == 0){
                                self.responseL.text = "no results"
                            }
                        DispatchQueue.main.async {
                            self.activityIndicator.stopAnimating()
                            self.activityIndicator.isHidden = true
                            self.responseL.isHidden = false
                        }
                    } catch _ {}
        }
    }
    task.resume()
2
Nirav D 15 dic. 2016 a las 15:10