This video has been archived, as it was published several years ago, so some of its information might now be outdated. For more recent articles, please visit the main article feed.
Swift clip: First class functions
Welcome to Swift Clips — a new series of shorter videos showcasing interesting and useful Swift tips and techniques. In this first episode we’ll take a look at first class functions, which is a language feature that enables us to use functions in really powerful ways.
Sample code
Adding a series of views as subviews of another view:
let view: UIView = ...
let subviews: [UIView] = [button, label, imageView]
// Using a closure
subviews.forEach { subview in
view.addSubview(subview)
}
// Using first class functions
subviews.forEach(view.addSubview)
Converting an array of strings into URL
values:
let strings = ["swiftbysundell.com", "apple.com"]
// Using a closure
let urls = strings.compactMap { string in
URL(string: string)
}
// Using first class functions
let urls = strings.compactMap(URL.init)
Sorting an array of Int
values in descending order:
let scores: [Int] = [9, 20, 2, 1, 5]
// Using a closure
let highScores = scores.sorted(by: { $0 > $1 })
// Using first class functions
let highScores = scores.sorted(by: >)
Applying a value to a closure, to avoid the classic “weak self dance”:
// A view controller that currently captures 'self' weakly, in
// order to call a method on a 'productManager' property object:
class ProductViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
buyButton.handler = { [weak self] in
guard let self = self else {
return
}
self.productManager.startCheckout(for: self.product)
}
}
}
// Introducing a 'combine' function for applying a value to
// any function or closure:
func combine<A, B>(
_ value: A,
with closure: @escaping (A) -> B
) -> () -> B {
return { closure(value) }
}
// Using our new combine function:
class ProductViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
buyButton.handler = combine(product,
with: productManager.startCheckout
)
}
}