Skip to content

Instantly share code, notes, and snippets.

@michalciurus
Created July 6, 2016 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michalciurus/f521096fd6c361986ff9a1619d07de8c to your computer and use it in GitHub Desktop.
Save michalciurus/f521096fd6c361986ff9a1619d07de8c to your computer and use it in GitHub Desktop.

Swift Coding Guidelines

General

• Use self only when needed. Avoid if possible.
• Prefer let over var
• Use guard as often as possible, instead of nesting ifs.

Header documentation

Quick Help offers concise in-line reference docs for symbols, build settings, and interface objects. Add Quick Help to annotate your code and create custom information that displays via pop-ups (option-click symbols) and the Quick Help inspector (View > Utilities > Show Quick Help Inspector).

Please annotate all things you consider worth annotating (especially public classes, structs, methods, properties). Thanks to this your fellow developers will be happy and will buy you a 🍺!

/// ---
/// # Subtitle 1
/// ## Subtitle 2
/// This is a *boring* list:
/// + First point
///   1. subpoint with **bold text**
///
/// Some code - indented by four spaces
///
///     let flag = someFunction()
/// ---
/// seealso: [Apple web site](www.apple.com)

Make classes final by default

Classes should start as final, and only be changed to allow subclassing if a valid need for inheritance has been identified. Even in that case, as many definitions as possible within the class should be final as well, following the same rules (but remember you don't have to mark every method final as it'll be inferred from the context).

Rationale: Composition is usually preferable to inheritance, and opting in to inheritance hopefully means that more thought will be put into the decision.

Return and break early

When you have to meet certain criteria to continue execution, try to exit early. So, instead of this:

if n.isNumber {
    // Use n here
} else {
    return
}

use this:

guard n.isNumber else {
    return
}
// Use n here

You can also do it with if statement, but using guard is preferred, because guard statement without return, break or continue produces a compile-time error, so exit is guaranteed.

Separating methods

Always separate your methods by using extensions. This is a great way to divide your file into logical chunks. public, private, delegate methods should always be in separate classes/extensions:

// Put your public/internal methods in the original class implementation
class Party {
    internal func method() {

    }
}
// Create extensions for protocol methods
extension Party : UIViewControllerPreviewingDelegate {
    // Delegate methods
}
// Create extensions for private methods
private extension Party {
    // This method is private, because the extension is private
    // No need to mark as private
    func privateMethod() {

    }
}

Force Unwrapping

Use force unwrapping only as a way to assert/quit early and unable to recover.

In order to enforce using that that, use only the !! custom operator from Chris Eidhof's book.

// Something went wrong, the login token should not be nil. Exit early if it is.
let processedToken = processToken(loginToken !! "Error. Token not available!")

Closures

Use [weak self] by default. Also use the weak self, strong self dance to make sure that the closure is atomic.

var _: () -> Void = { [weak self] in
  if let strongSelf = self {
    strongSelf.method1()
    strongSelf.method2()
    strongSelf.method3()
  }
}

Setting up views

Instead of cluttering viewDidLoad with all the setting up the views code, put them in relevant places in the class.

• Use closures for setting up fresh views

class ViewController: UIViewController {
    let topView: UIView = {
        let view = UIView()
        view.frame = CGRect(x: 0, y: 0, width: 100, height: 200)
        view.backgroundColor = UIColor.redColor()
        return view
    }()
}

• Use didSet to setup xib/storyboard views:

@IBOutlet weak var arrivalLabel: UILabel! {
    didSet {
        arrivalLabel.text = "Arriving in 10 minutes".uppercaseString
        arrivalLabel.font = UIFont(name: "CirceBold", size: 11)
        arrivalLabel.textColor = UIColor.blueColor()
        arrivalLabel.textAlignment = .Center
        arrivalLabel.numberOfLines = 1
    }
}

Constants

Try to put the constants in relevant files. Put the constants in accordingly named structs.

struct LoginViewControllerConstants {
  static let myConstant = 3
}

Use typealias to make using constants easier.

typealias C = LoginViewControllerConstants
let myHeight = C.myConstant
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment