Use extensions to implement protocols

In order to keep code organized, whenever you need to implement a protocol, prefer doing it in an extension, so logic related code is kept near. Protocols that are automatically implemented, like Codable, should be kept at the type declaration.

class Model: Codable {
	let id: Int
	let name: String
}

extension Model: Equatable {
	// ...
}

extension Model: Hashable {
	// ...
}

Use callbacks, not delegates

Delegates are a thing of the past, they were useful when Objective-C was king, but now with swift, we can do things better.

class SomeView: UIView {
	public var onDiscard: (() -> Void)?
	public var onOptionSelect: ((Int) -> Void)?

	private func optionSelect() {
		guard let onOptionSelect = onOptionSelect else { return }
		onOptionSelect(someValue)
	}
}

// then

let someView = SomeView()
someView.onOptionSelect = { option in
	print("option", option)
}

Callback rules

Always omit parenthesis on callback arguments, even if more than one, to reduce visual clutter.

someCallback = { argument in
	// ...
}

otherCallback = { even, more, arguments in
	// ...
}

Always weakly capture self if used inside the callback, to avoid memory leaks. If you need a strong reference to self, you should guard let it.

usingSelfCallback = { [weak self] in
	// ...
	self?.something()
}

guardingSelfCallback = { [weak self] in
	guard let self = self else { return }
	// ...
}

Avoid boolean comparisons

As found in this swift forum post, comparing a boolean variable with true or false is extremely slow con compile times. Because of this, we should avoid it:

let something: Bool = true

// Don't
if something == true {}
if something == false {}

// Do
if something {}
if !something {}

When dealing with optional booleans, we should always try to unwrap them first:

let something: Bool? = true

// Don't
if something == true {}
if something == false {}

// Do
if let something = something, something {}

Avoid magic numbers