Articles and podcasts about Swift development, by John Sundell.

Genius Scan SDK

Presented by the Genius Scan SDK

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

Published on 16 Jan 2020

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
        )
    }
}