Reference of this way to specify function handler using closure?

Hi! I encountered a way of specifying completion handler that I don't understand. I am trying to find some swift syntax. Can you help me to find a link or some hint to understand how this works?


Following the example in https://www.raywenderlich.com/3244963-urlsession-tutorial-getting-started

I got the following code working and printing the expected message. However, the way it specify completion handler is not to pass the closure into the "dataTask" method call as a parameter, but just placing after the method call.

var sharedSession : URLSession = URLSession.shared
var googUrl:URL = URL(string: "https://www.google.ca/finance")!
var task1: URLSessionDataTask = sharedSession.dataTask(with: googUrl) {
    data, response, error in
    print("task 1 completed.")
}


I looked at the reference at https://developer.apple.com/documentation/foundation/urlsession

Seems the right way to specify the handler is passing it as parameter as follow

var task1: URLSessionDataTask = sharedSession.dataTask(with: googUrl, completionHandler: {
    data, response, error in
    print("task 1 completed.")
})


Why the former works?


Thank you!

Accepted Reply

When you pass a closure as the last parameter, you have the option to write the closure AFTER the closing parenthesis.


Here is a simple example with the map function:


let numbers = [1, 2, 3]
let mappedNumbers = numbers.map({ number in 3 * number })
let mappedNumbers2 = numbers.map(){ number in 3 * number }



Read Functions and Closures in Apple Inc. « The Swift Programming Language (Swift 4). » Apple Books.


« You can refer to parameters by number instead of by name—this approach is especially useful in very short closures. A closure passed as the last argument to a function can appear immediately after the parentheses. When a closure is the only argument to a function, you can omit the parentheses entirely. »



So you couls also write the previous map as

let mappedNumbers3 = numbers.map  { number in 3 * number }

Replies

When you pass a closure as the last parameter, you have the option to write the closure AFTER the closing parenthesis.


Here is a simple example with the map function:


let numbers = [1, 2, 3]
let mappedNumbers = numbers.map({ number in 3 * number })
let mappedNumbers2 = numbers.map(){ number in 3 * number }



Read Functions and Closures in Apple Inc. « The Swift Programming Language (Swift 4). » Apple Books.


« You can refer to parameters by number instead of by name—this approach is especially useful in very short closures. A closure passed as the last argument to a function can appear immediately after the parentheses. When a closure is the only argument to a function, you can omit the parentheses entirely. »



So you couls also write the previous map as

let mappedNumbers3 = numbers.map  { number in 3 * number }

I am trying to find some swift syntax.

Here it is: Trailing Closures


Another example:

func doRepeating(_ count: Int, task: ()->Void) {
    for _ in 0..<count {
        task()
    }
}

doRepeating(3, task: {print("*", terminator: "")}) //->***

You know `{print("*", terminator: "")}` is a closure and passed to the parameter `task`.


In Swift, when the last parameter of a function is a closure type, you can write it in this way:

doRepeating(3) {print("*", terminator: "")}

Or:

doRepeating(3) {
    print("*", terminator: "")
}

In this notation, `{print("*", terminator: "")}` may not look like a closure but it is. The closure is passed to the parameter `task`.


So, the two notations that you have found are strictly identical, the closure is passed to `completionHandler`.

And you can also skip the parameter label:


let sortedNumbers1 = numbers.sorted (by: { $0 > $1 })

is equivalent to

let sortedNumbers2 = numbers.sorted { $0 > $1 }


Read the Closures chapter in Swift reference for details.

Thank you Claude31!

With the information from you I found the reference for Swift 5.1. This way of using it is called "Trailing Closures".

https://docs.swift.org/swift-book/LanguageGuide/Closures.html

Thank you for the example!