One way to enforce good software design and architecture is by using boiler plate code. Xcode supports custom file templates to help with this.

Let’s walk through creating a custom template for a UIViewController. First we will create the directory that Xcode looks for templates in. Then we will copy a template into this directory that we can edit.

$ mkdir -p ~/Library/Developer/Xcode/Templates/File\ Templates/Custom
$ cd ~/Library/Developer/Xcode/Templates/File\ Templates/Custom
$ cp /Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File\ Templates/Source/Swift\ File.xctemplate Swift\ UIViewController.xctemplate

Next open up TemplateInfo.plist.

 $ open Swift\ UIViewController.xctemplate/TemplateInfo.plist 

You will want to edit the Description and Summary fields.

Next open up ___FILEBASENAME__.swift.

$ open Swift\ UIViewController.xctemplate/___FILEBASENAME___.swift 

I like to split up my UIViewControllers using extensions. IBOutlets, members, and existing initializer‘s must be in the class declaration. However, lifecycle code can be in an extension. I also put segues and actions in their own extensions.

//___FILEHEADER___

import UIKit

class ___FILEBASENAMEASIDENTIFIER___: UIViewController {

    // MARK: - IBOutlets

    // MARK: - Members

    // MARK: - Initializers
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension ___FILEBASENAMEASIDENTIFIER___ {
    
    // MARK: - View lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }

   override  func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }

   override  func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
    }
}

extension ___FILEBASENAMEASIDENTIFIER___ {
    
    // MARK: - Segues
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Inject dependencies in child viewcontrollers
    }
}

extension ___FILEBASENAMEASIDENTIFIER___ {
    // MARK: - IBActions
    
}

Now when you create a File -> New -> File, the Swift UIViewController template appears in the dialog box.

Custom Template