General documentation / cheat sheets for various languages and services

References

UIFont

Built-in font sizes (with absolute values from iOS Simulator Playground), from smallest to largest:

Constant Pts
UIFont.smallSystemFontSize 12.0
UIFont.systemFontSize 14.0
UIFont.labelFontSize 17.0
UIFont.buttonFontSize 18.0
// small normal system font
UIFont.systemFont(ofSize: UIFont.smallSystemFontSize)

// larger bold system font
UIFont.boldSystemFont(ofSize: UIFont.labelFontSize)

Grand Central Dispatch

Gotchas

Apparently anonymous functions cannot have arguments labels in Swift, which is maybe one reason why anonymous instantiations / reifications of protocols aren’t supported.

Error explanations

Using self initializer from static function

If your subclass has a static method that tries to use self.init(...) to create a new instance:

class MyViewController: UIViewController, UIViewControllerRestoration {
    static func viewController(withRestorationIdentifierPath identifierComponents: [Any], coder: NSCoder) -> UIViewController? {
        return self.init()
    }
}

You might get this error message:

Constructing an object of class type 'MyViewController' with a metatype value must use a 'required' initializer.

One solution is to just call MyViewController(...), but another fix is to set the class to final: final class MyViewController: UIViewController, UIViewControllerRestoration { ... }

Recipes

/**
Get the date of the current build by reading the `creationDate` of the bundle's `Info.plist` file.
This is not always accurate due to Xcode caching parts of the build process that are not materially changed.
To ensure an accurate reading, `Clean` your project before rebuilding.

Based on https://stackoverflow.com/a/38421481
*/
private func readBuildDate() -> Date? {
    let bundleName = Bundle.main.infoDictionary!["CFBundleName"] as? String ?? "Info.plist"
    if let bundleResourcePath = Bundle.main.path(forResource: bundleName, ofType: nil),
        let bundleResourceAttributes = try? FileManager.default.attributesOfItem(atPath: bundleResourcePath),
        let bundleDate = bundleResourceAttributes[.creationDate] as? Date {
        return bundleDate
    }
    return nil
}