How could I create a function with a completion handler in Swift?
Asked Answered
M

9

181

I was just curious as to how I would approach this. If I had a function, and I wanted something to happen when it was fully executed, how would I add this into the function? Thanks

Mortensen answered 22/5, 2015 at 16:13 Comment(1)
@Bright, the video is unavailable...Teen
S
224

Say you have a download function to download a file from network, and want to be notified when download task has finished.

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
    }
})
Succinate answered 22/5, 2015 at 16:21 Comment(4)
This would work great, but more out of curiosity, I was wondering if you could somehow write a completion handler into your function.Mortensen
Hi Floks, I want to call this CompletionHandler from other function so how to achieve this??Obediah
any example for objective cTallow
When I call it by another class it not sowing completion handler success parameter.Olympie
C
123

I had trouble understanding the answers so I'm assuming any other beginner like myself might have the same problem as me.

My solution does the same as the top answer but hopefully a little more clear and easy to understand for beginners or people just having trouble understanding in general.

To create a function with a completion handler

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

     print("Doing something!")

     finished()

}

to use the function

     override func viewDidLoad() {
    
          yourFunctionName {
         
          //do something here after running your function
           print("Tada!!!!")
          }
    
    }

Your output will be

Doing something

Tada!!!

Compunction answered 8/1, 2017 at 23:29 Comment(0)
P
113

Simple Example:

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

How to use it:

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")
    }
})
Pancreas answered 10/4, 2017 at 7:34 Comment(0)
P
27

Swift 5.0 + , Simple and Short

example:

Style 1

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

          print("block_Completion")
          completionBlock()
    }

Style 2

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

        print("block_Completion")
        completionBlock()
    }

Use:

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

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

Output

block_Completion

Doing something after Block_Completion!!

Pedro answered 20/12, 2019 at 11:18 Comment(0)
D
14

We can use Closures for this purpose. Try the following

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

At some point we can call this function as given below.

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

Please refer the following link for more information regarding Closures.

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

Daune answered 20/1, 2016 at 19:57 Comment(0)
G
3

In case you need result values in your completion handler, it's a good idea to include labels proceeded with underscores, like this...

func getAccountID(account: String, completionHandler: (_ id: String?, _ error: Error?) -> ()) {
    
    // Do something and return values in the completion handler
    completionHandler("123", nil)
}

...because when you type this function, Xcode will automatically fill in the result value labels, like this:

getAccountID(account: inputField.stringValue) { id, error in
        
}
Granivorous answered 2/2, 2023 at 19:2 Comment(0)
W
1

In addition to above : Trailing closure can be used .

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

  // When download completes,control flow goes here.
  if success {
      // download success
  } else {
    // download fail
  }
}
Whopping answered 27/8, 2016 at 17:5 Comment(0)
I
0

I'm a little confused about custom made completion handlers. In your example:

Say you have a download function to download a file from network,and want to be notified when download task has finished.

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

Your // download code will still be ran asynchronously. Why wouldn't the code go straight to your let flag = true and completion Handler(success: flag) without waiting for your download code to be finished?

Inebriate answered 6/1, 2016 at 23:55 Comment(1)
Eventually, something has to sit and wait for code to run, it's not a giant tower of asynchronous elephants all the way down. "Ran asynchronously" means that there are two threads. One of them sits and waits for the task to be done, the other carries on and does not. The completion handler gets called, or at least scheduled to be called, at the end of the thread that does the work.Waikiki
V
0
//MARK: - Define
typealias Completion = (_ success:Bool) -> Void
//MARK: - Create
func Call(url: NSURL, Completion: Completion) {
      Completion(true)
}
//MARK: - Use
Call(url: NSURL(string: "http://")!, Completion: { (success) -> Void in
    if success {
        //TRUE
    } else {
        //FALSE
    }
})
Verdie answered 21/7, 2022 at 10:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.