¿Cómo podría crear una función con un controlador de finalización en Swift?

116

Solo tenía curiosidad por saber cómo abordaría esto. Si tuviera una función y quisiera que sucediera algo cuando se ejecutara por completo, ¿cómo agregaría esto a la función? Gracias

traw1233
fuente
2
Hay un video increíble en Youtube: google.com/…
Bright Future

Respuestas:

174

Supongamos que tiene una función de descarga para descargar un archivo de la red y desea recibir una notificación cuando finalice la tarea de descarga.

typealias CompletionHandler = (success:Bool) -> Void

func downloadFileFromURL(url: NSURL,completionHandler: CompletionHandler) {

    // download code.

    let flag = true // true if download succeed,false otherwise

    completionHandler(success: flag)
}

// How to use it.

downloadFileFromURL(NSURL(string: "url_str")!, { (success) -> Void in

    // When download completes,control flow goes here.
    if success {
        // download success
    } else {
        // download fail
    }
})

Espero eso ayude.

tounaobun
fuente
2
Esto funcionaría muy bien, pero más por curiosidad, me preguntaba si de alguna manera podría escribir un controlador de finalización en su función.
traw1233
1
Hola Floks, quiero llamar a este CompletionHandler desde otra función, entonces, ¿cómo lograrlo?
Himanshu jamnani
cualquier ejemplo para el objetivo c
Xcodian Solangi
Cuando lo llamo por otra clase, no sembra el parámetro de éxito del controlador de finalización.
Chandni
85

Tuve problemas para entender las respuestas, así que supongo que cualquier otro principiante como yo podría tener el mismo problema que yo.

Mi solución hace lo mismo que la respuesta principal, pero espero que sea un poco más clara y fácil de entender para principiantes o personas que simplemente tienen problemas de comprensión en general.

Para crear una función con un controlador de finalización

func yourFunctionName(finished: () -> Void) {

     print("Doing something!")

     finished()

}

para usar la función

     override func viewDidLoad() {

          yourFunctionName {

          //do something here after running your function
           print("Tada!!!!")
          }

    }

Tu salida será

Haciendo algo

Tada !!!

¡Espero que esto ayude!

Cirilo
fuente
80

Ejemplo simple de Swift 4.0:

func method(arg: Bool, completion: (Bool) -> ()) {
    print("First line of code executed")
    // do stuff here to determine what you want to "send back".
    // we are just sending the Boolean value that was sent in "back"
    completion(arg)
}

Cómo usarlo:

method(arg: true, completion: { (success) -> Void in
    print("Second line of code executed")
    if success { // this will be equal to whatever value is set in this method call
          print("true")
    } else {
         print("false")
    }
})
Poli
fuente
12

Podemos utilizar cierres para este propósito. Prueba lo siguiente

func loadHealthCareList(completionClosure: (indexes: NSMutableArray)-> ()) {
      //some code here
      completionClosure(indexes: list)
}

En algún momento podemos llamar a esta función como se indica a continuación.

healthIndexManager.loadHealthCareList { (indexes) -> () in
            print(indexes)
}

Consulte el siguiente enlace para obtener más información sobre cierres .

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html

arango_86
fuente
5

Swift 5.0 +, simple y corto

ejemplo:

Estilo 1

    func methodName(completionBlock: () -> Void)  {

          print("block_Completion")
          completionBlock()
    }

Estilo 2

    func methodName(completionBlock: () -> ())  {

        print("block_Completion")
        completionBlock()
    }

Utilizar:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        methodName {

            print("Doing something after Block_Completion!!")
        }
    }

Salida

block_Completion

Haciendo algo después de Block_Completion !!

Lakhdeep Singh
fuente
0

Estoy un poco confundido acerca de los controladores de finalización personalizados. En tu ejemplo:

Supongamos que tiene una función de descarga para descargar un archivo de la red y desea recibir una notificación cuando finalice la tarea de descarga.

typealias CompletionHandler = (success:Bool) -> Void

func downloadFileFromURL(url: NSURL,completionHandler: CompletionHandler) {

    // download code.

    let flag = true // true if download succeed,false otherwise

    completionHandler(success: flag)
}

Su // download codetodavía se corrió de forma asíncrona. ¿Por qué no el código de ir directamente a tu let flag = truey completion Handler(success: flag)sin esperar a que su código de descarga para ser terminado?

Respiración fuerte
fuente
Eventualmente, algo tiene que sentarse y esperar a que se ejecute el código, no es una torre gigante de elefantes asincrónicos hasta el final. "Se ejecutó de forma asincrónica" significa que hay dos subprocesos. Uno de ellos se sienta y espera a que termine la tarea, el otro continúa y no lo hace. El controlador de finalización es llamado, o al menos programado para ser llamado, al final del hilo que hace el trabajo.
Crowman
0

Además de lo anterior: se puede utilizar un cierre posterior.

downloadFileFromURL(NSURL(string: "url_str")!)  { (success) -> Void in

  // When download completes,control flow goes here.
  if success {
      // download success
  } else {
    // download fail
  }
}
Shrawan
fuente