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


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.


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!


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")
    }
})

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


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 !!


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?


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
  }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.