Tengo un UIViewController que carga algunos datos json del servidor. Si el servidor está inactivo o el usuario tiene datos desactivados, lanzo una alerta informándole al usuario. Esto se hace usando un UIAlertController. Esto funciona muy bien. Así que puse esto en una extensión, ya que lo utilizan todos los UIViewControllers que necesitan datos. Ahora el UIAlertController también tiene un conjunto de acciones

Código de alerta

extension UIViewController {    
func connectionLost(){
    var message = "Your device has lost connection to the server. Check that you have a valid internet connection and then retry."

    let alertController = UIAlertController( title: "Connection Lost",
                                             message: message,
                                             preferredStyle: .alert)
    let retryAction = UIAlertAction(title:"Retry", style: .default, handler: {
        action in

        //call function in the viewcontroller that raised this alert to reload the data
    })
    alertController.addAction(retryAction)
    self.present(alertController, animated: true, completion: nil)
}
}

Cuando el usuario toca el botón de reintento, quiero llamar a una función en el uiviewcontroller que generó la alerta.

Intenté crear un delegado en la extensión, pero tuve problemas para conectarlo como lo hace en una clase. ¿Qué tipo de enfoques existen para llamar a una función desde una extensión en el controlador de vista que generó la alerta?

1
Micah Montoya 13 dic. 2016 a las 18:00

2 respuestas

La mejor respuesta

Debes crear un BaseViewController y usar Herencia. También podría ser útil para otras implementaciones.

class BaseViewController: UIViewController {

    func onRetryClick() {
        // override to customize or write here the common behaviour
    }
}

class FirstViewController: BaseViewController {
    override func onRetryClick() {
        // do something specific for FirstViewController
    }
}

class SecondViewController: BaseViewController {
    override func onRetryClick() {
        // do something specific for SecondViewController
    }
}

class ThirdViewController: BaseViewController {
    // if you don't override this method, super class (BaseViewController) implementation will be executed
}

extension BaseViewController {    

    func connectionLost(){
        var message = "Your device has lost connection to the server. Check that you have a valid internet connection and then retry."

        let alertController = UIAlertController( title: "Connection Lost",
                                             message: message,
                                             preferredStyle: .alert)
        let retryAction = UIAlertAction(title:"Retry", style: .default, handler: { action in
            self.onRetryClick()
        })

        alertController.addAction(retryAction)
        self.present(alertController, animated: true, completion: nil)
    }
}
2
lubilis 13 dic. 2016 a las 15:28

Espero que esto tenga sentido.

class MyVC: UIViewController {

    func retry() {

    }

    func checkConnection() {
        connectionLost { (retry) -> (Void) in
            if retry {
                self.retry()
            }
        }
    }
}


extension UIViewController {
    func connectionLost(completion: @escaping (_ retry: Bool) -> (Void)) {
        let message = "Your device has lost connection to the server. Check that you have a valid internet connection and then retry."

        let alertController = UIAlertController( title: "Connection Lost",
                                             message: message,
                                             preferredStyle: .alert)
        let retryAction = UIAlertAction(title:"Retry", style: .default, handler: {
        action in
            completion(true)//may be 'false', you decide
        })
        alertController.addAction(retryAction)
        self.present(alertController, animated: true, completion: nil)
    }
}
0
Santosh 13 dic. 2016 a las 15:42