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

FunctionSwiftCompletionhandler

Function Problem Overview


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

Function Solutions


Solution 1 - Function

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

Hope it helps.

Solution 2 - Function

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

Hope this helps!

Solution 3 - Function

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

Solution 4 - Function

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

Solution 5 - Function

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

Solution 6 - Function

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

Solution 7 - Function

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?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiontraw1233View Question on Stackoverflow
Solution 1 - FunctiontounaobunView Answer on Stackoverflow
Solution 2 - FunctionCyrilView Answer on Stackoverflow
Solution 3 - FunctionBobbyView Answer on Stackoverflow
Solution 4 - FunctionLakhdeep SinghView Answer on Stackoverflow
Solution 5 - Functionarango_86View Answer on Stackoverflow
Solution 6 - FunctionShrawanView Answer on Stackoverflow
Solution 7 - FunctionHeavy BreathingView Answer on Stackoverflow