DEV Community

Ajithmadhan
Ajithmadhan

Posted on

Swift - Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

Closures can capture and store references to any constants and variables from the context in which they’re defined. This is known as closing over those constants and variables.

Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:

  • Global functions are closures that have a name and don’t capture any values.
  • Nested functions are closures that have a name and can capture values from their enclosing function.
  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Closure expressions

closure expression is a way of working inline closures in a brief, forward syntax.

  • closures are special type of function without function name.

Swift closure declaration syntax.

{(parameter) -> returnType in 
// statement
}

Enter fullscreen mode Exit fullscreen mode

in - used to separate parameters/return type from closure body.

//Sorting backwards
func backwards(name1:Int ,name2:Int) -> Bool{
    return name1 > name2
}

let nums = [2,5,7,2,8,9,5,4,6]
let SortedNums = nums.sorted(by: backwards(name1:name2:))

let SortedNums = nums.sorted(by: {(s1:Int,s2:Int) -> Bool in return s1 > s2})

//Inferring Type From Context
let SortedNums = nums.sorted(by: {s1,s2 in return s1>s2 })

//Implicit Returns from Single-Expression Closures
let SortedNums = nums.sorted(by: {s1,s2 in s1>s2 })


//Shorthand Argument Names
let SortedNums = nums.sorted(by: {$0 > $1})

//Operator Methods
let SortedNums = nums.sorted(by: >)

print(SortedNums)
Enter fullscreen mode Exit fullscreen mode

Trailing Closures

If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. You write a trailing closure after the function call’s parentheses, even though the trailing closure is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the first closure as part of the function call. A function call can include multiple trailing closures;


//trailing closures
let SortedNums = nums.sorted() {$0 > $1}
let SortedNums = nums.sorted {$0 > $1}
Enter fullscreen mode Exit fullscreen mode

Capturing values

A closure can capture constants and variables from the surrounding context in which it’s 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.

Closures are reference type

Escaping Closures

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

By default closures are non escaping

func sayHii(name:String , sayIt: @escaping(String) ->Void){
    let fullName = name.uppercased()
    DispatchQueue.main.asyncAfter(deadline: .now()+3) {
        sayIt(fullName)
    }
}

sayHii(name: "ajith") { name in
    print(name)
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)