The question might be a little broad, but I will try to recap.
Referring to the Documentation:
Closures are self-contained blocks of functionality that can be passed
around and used in your code.
You should use closure(s) when you want to pass a chunk of code as a parameter to a method that you want to execute it asynchronously.
To make it simpler -by giving a real-world example-, imagine that there is a method responsible for scanning the user's photos, so the method should returns an array of photos and another array of videos:
Pesudo-code:
// the method should scan the the user's photos and return them after fetching is finished
// the 'completion' (success) closure should returns two arrays
// what if there is something wrong happened? another closure should returns an error
// for the example purposes they are arrays of strings, the error is also a string
func scanPhotos( completion: @escaping (_ photos: [String], _ videos: [String]) -> (), failure: @escaping (String) -> ()) {
// imagine that the scanning has been successfully done and you filled the two arrays:
//if scanningSuccess {
let fetchedPhotos = [String]()
let fetchedVideos = [String]()
completion(fetchedPhotos, fetchedVideos)
//} else {
// if something goes wrong
failure("the error!!")
//}
}
Calling the method:
scanPhotos(completion: { (photos, videos) in
// now you can use the fetched photos and videos
}, failure: { error in
// display an alert -for example- based on the error is saying...
})
Note the the scanning proccess should be executed asynchronously, when it finished, one of the two blocks (success or failure) should be executed.
Some of the popular methods that work with clousres:
AGAIN: it is just a simple usage of the closures; You need to check the documentation for more details.
I hope it helped.