A classic sight at the top of a view controller is a list of views being instantiated and some properties being set on each:

let contentView: UIView = {

let v = UIView()

v.backgroundColor = .red

v.clipsToBounds = true

return v

}() let titleLabel: UILabel = {

let l = UILabel()

l.font = .systemFont(ofSize: 22)

l.textColor = .red

l.text = "WELCOME"

return l

}() let stackView: UIStackView = {

let s = UIStackView()

s.axis = .vertical

s.distribution = .fillEqually

s.alignment = .center

s.spacing = 8

return s

}()

When I look at that code, I can’t help but feel that there’s some redundant and duplicate information, specifically:

So, I created a function that can be used to make setup closures a lot neater:

func create<T>(_ setup: ((T) -> Void)) -> T where T: NSObject {

let obj = T()

setup(obj)

return obj

}

This function sits above everything and can instantiate any NSObject subclass that doesn’t need arguments passed to it’s init . Now if we were to re-write our setup closure list it will only have the bare minimum of scaffolding the compiler requires:

let contentView: UIView = create {

$0.backgroundColor = .red

$0.clipsToBounds = true

} let titleLabel: UILabel = create {

$0.font = .systemFont(ofSize: 22)

$0.textColor = .red

$0.text = "WELCOME"

} let stackView: UIStackView = create {

$0.axis = .vertical

$0.distribution = .fillEqually

$0.alignment = .center

$0.spacing = 8

}

This works by taking advantage of the following Swift language features:

A function’s return value can be generically inferred by the type it is being assigned to, for example func x<ReturnType>() -> ReturnType

The last closure argument of a function can be written as a closure outside of the function, for example array.forEach { … }

Closure arguments don’t need to be named; it’s possible to use $0 instead, for example array.compactMap { $0 }

So now the property’s type only needs to appear once and we don’t need to create a variable in the scope of a closure that we call immediately!