Come posso creare una funzione con un gestore di completamento in Swift?


116

Ero solo curioso di sapere come mi sarei avvicinato a questo. Se avessi una funzione e volessi che accadesse qualcosa quando è stata completamente eseguita, come la aggiungerei alla funzione? Grazie


2
C'è un video fantastico su Youtube: google.com/…
Bright Future

Risposte:


174

Supponiamo che tu abbia una funzione di download per scaricare un file dalla rete e desideri essere avvisato quando l'attività di download è terminata.

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

Spero che sia d'aiuto.


2
Funzionerebbe benissimo, ma più per curiosità, mi chiedevo se potessi in qualche modo scrivere un gestore di completamento nella tua funzione.
traw1233

1
Ciao Floks, voglio chiamare questo CompletionHandler da un'altra funzione, quindi come ottenerlo ??
Himanshu jamnani

qualsiasi esempio per l'obiettivo c
Xcodian Solangi

Quando lo chiamo da un'altra classe non semina il parametro di successo del gestore di completamento.
Chandni

85

Ho avuto problemi a capire le risposte, quindi presumo che qualsiasi altro principiante come me potrebbe avere lo stesso problema come me.

La mia soluzione è uguale alla risposta principale, ma si spera un po 'più chiara e facile da capire per i principianti o per le persone che hanno difficoltà a capire in generale.

Per creare una funzione con un gestore di completamento

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

     print("Doing something!")

     finished()

}

per utilizzare la funzione

     override func viewDidLoad() {

          yourFunctionName {

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

    }

La tua uscita sarà

Facendo qualcosa

Tada !!!

Spero che questo ti aiuti!


80

Semplice esempio di 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)
}

Come 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

Possiamo usare le chiusure per questo scopo. Prova quanto segue

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

Ad un certo punto possiamo chiamare questa funzione come indicato di seguito.

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

Fare riferimento al seguente collegamento per ulteriori informazioni sulle chiusure .

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


5

Swift 5.0 +, semplice e breve

esempio:

Stile 1

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

          print("block_Completion")
          completionBlock()
    }

Stile 2

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

        print("block_Completion")
        completionBlock()
    }

Uso:

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

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

Produzione

block_Completion

Fare qualcosa dopo Block_Completion !!


0

Sono un po 'confuso riguardo ai gestori di completamento personalizzati. Nel tuo esempio:

Supponiamo che tu abbia una funzione di download per scaricare un file dalla rete e desideri essere avvisato quando l'attività di download è terminata.

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

Il tuo // download codeverrà comunque eseguito in modo asincrono. Perché il codice non andrebbe direttamente al tuo let flag = truee completion Handler(success: flag)senza attendere che il codice di download sia terminato?


Alla fine, qualcosa deve sedersi e aspettare che il codice venga eseguito, non è una gigantesca torre di elefanti asincroni fino in fondo. "Ran asynchronously" significa che sono presenti due thread. Uno di loro si siede e aspetta che il compito venga svolto, l'altro continua e non lo fa. Il gestore di completamento viene chiamato, o almeno pianificato per essere chiamato, alla fine del thread che esegue il lavoro.
Crowman

0

In aggiunta a quanto sopra: può essere utilizzata la chiusura finale .

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

  // When download completes,control flow goes here.
  if success {
      // download success
  } else {
    // download fail
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.