Como posso criar uma função com um manipulador de conclusão em Swift?

116

Eu estava apenas curioso para saber como abordaria isso. Se eu tivesse uma função e quisesse que algo acontecesse quando ela fosse totalmente executada, como adicionaria isso à função? obrigado

traw1233
fonte
2
Há um vídeo incrível no Youtube: google.com/…
Bright Future

Respostas:

174

Digamos que você tenha uma função de download para baixar um arquivo da rede e deseja ser notificado quando a tarefa de download for concluída.

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 que ajude.

Tounaobun
fonte
2
Isso funcionaria muito bem, mas mais por curiosidade, gostaria de saber se você poderia de alguma forma escrever um manipulador de conclusão em sua função.
traw1233
1
Oi Floks, Eu quero chamar este CompletionHandler de outra função, então como fazer isso ??
Himanshu jamnani
qualquer exemplo para o objetivo c
Xcodian Solangi
Quando eu o chamo por outra classe, ele não semeia o parâmetro de sucesso do manipulador de conclusão.
Chandni
85

Tive dificuldade em entender as respostas, então presumo que qualquer outro iniciante como eu possa ter o mesmo problema que eu.

Minha solução faz o mesmo que a resposta principal, mas espero que seja um pouco mais clara e fácil de entender para iniciantes ou pessoas com dificuldade de entender em geral.

Para criar uma função com um manipulador de conclusão

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

     print("Doing something!")

     finished()

}

usar a função

     override func viewDidLoad() {

          yourFunctionName {

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

    }

Sua saída será

Fazendo algo

Tada !!!

Espero que isto ajude!

Cirilo
fonte
80

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

Como usá-lo:

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")
    }
})
Bobby
fonte
12

Podemos usar Closures para este propósito. Tente o seguinte

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

Em algum ponto, podemos chamar essa função conforme fornecido a seguir.

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

Consulte o link a seguir para obter mais informações sobre fechamentos .

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

arango_86
fonte
5

Swift 5.0 +, simples e curto

exemplo:

Estilo 1

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

          print("block_Completion")
          completionBlock()
    }

Estilo 2

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

        print("block_Completion")
        completionBlock()
    }

Usar:

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

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

Resultado

block_Completion

Fazendo algo após Block_Completion !!

Lakhdeep Singh
fonte
0

Estou um pouco confuso sobre manipuladores de conclusão personalizados. No seu exemplo:

Digamos que você tenha uma função de download para baixar um arquivo da rede e deseja ser notificado quando a tarefa de download for concluída.

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

Seu // download codecontinuará sendo executado de forma assíncrona. Por que o código não iria direto para você let flag = truee completion Handler(success: flag)sem esperar que o código de download fosse concluído?

Respiração pesada
fonte
Eventualmente, algo tem que sentar e esperar que o código seja executado, não é uma torre gigante de elefantes assíncronos até o fim. "Executado de forma assíncrona" significa que existem dois threads. Um deles senta e espera que a tarefa seja realizada, o outro continua e não o faz. O manipulador de conclusão é chamado, ou pelo menos agendado para ser chamado, no final do encadeamento que faz o trabalho.
Crowman
0

Além do acima: O fechamento à direita pode ser usado.

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

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