Swift 3.1 Closures

Created By: Debasis Das (14-May-2017)

Closures are self contained blocks of functionality that can be used in our code and pass around as function parameters
Closures in Swift are similar to blocks in Objective C

In the below sample we will create two functions and pass it as an argument to the sorted by function of an array

import Cocoa
var array = [23,21,76,12,79]

func descending(val1:Int, val2:Int)-> Bool{
    return val1 > val2
}
func ascending(val1:Int, val2:Int)-> Bool{
    return val1 < val2
}

var descendingArray = array.sorted(by: descending)
print(descendingArray) //[79, 76, 23, 21, 12]

var ascendingArray = array.sorted(by: ascending)
print(ascendingArray) //[12, 21, 23, 76, 79]

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 3.1).” iBooks. https://itun.es/us/jEUH0.l
“The sorted(by:) method accepts a closure that takes two arguments of the same type as the array’s contents, and returns a Bool value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return true if the first value should appear before the second value, and false otherwise.”

In the below sample we will use a closure expression syntax rather than sending a function as an argument to the sorted by method

var newDescendingArray = array.sorted { (num1:Int, num2:Int) -> Bool in
    return num1>num2
}
print(newDescendingArray) //[79, 76, 23, 21, 12]

Inferring Type from context

var names = ["John","Jim","Jane","Mary","Bill"]
var sortedNames = names.sorted { (s1, s2) -> Bool in
    return s1 < s2
}
print(sortedNames) //["Bill", "Jane", "Jim", "John", "Mary"]

Implicit Returns from Single-Expression Closures
Single-expression closures can implicitly return the result of their single expression by omitting the return keyword from their declaration

var sortedNames1 = names.sorted { (s1, s2) -> Bool in
    s1 < s2
}
print(sortedNames1) //["Bill", "Jane", "Jim", "John", "Mary"]

Shorthand Argument Names
Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2 etc

var sortedNames2 = names.sorted(by: { $0 < $1})
print(sortedNames2) //["Bill", "Jane", "Jim", "John", "Mary"]

Operator Methods
An even shorter way to write the above

var sortedNames3 = names.sorted(by:  > )
print(sortedNames3) //["Mary", "John", "Jim", "Jane", "Bill"]

Trailing closures

var sortedNames4 = names.sorted(){$0>$1}
print(sortedNames4) //["Mary", "John", "Jim", "Jane", "Bill"]


var monthNamesMap = [1:"Jan",2:"Feb",3:"Mar"]
let months = [1,2]
let monthNames = months.map { (number:Int) -> String in
    var name = ""
    name = monthNamesMap[number]!
    return name
}
print(monthNames) //["Jan", "Feb"]

Capturing values
A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.

var total = 0
var incrementTotal = {
    total += 1
}
var printTotal = {
    print("total is \(total)")
}
printTotal() //total is 0
incrementTotal()
printTotal() //total is 1
incrementTotal()
printTotal() //total is 2
Posted in Swift, Swift 3.1 Tagged with: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news