If you're working with swift and want to subclass something that implements NSCoding (like UIView, UIViewController, etc), you might find yourself in a bit of an annoying situation. Namely, the init(coder: aDecoder) initializer is required by the NSCoding protocol, which means you need to implement it if you override the designated initializer for your superclass.

That would be fine, but swift is also super strict about making sure all your class's properties are assigned a value in init(), before making a call to super.init(). This means that if you want to provide your own initializer, you can't do something like this:

class FooViewController: UIViewController {  
  let name: String

  init() {
    name = "Bar"
    super.init(nibName: nil, bundle:nil)
  }

  required init(coder: NSCoder) {
    super.init(coder: coder)
  }
}

The init(coder:) initializer didn't set the name property, so it won't compile. You could duplicate the initialization and set name in both initializers, but that sucks when you've got a lot going on in init (which you should, if you want to avoid optional properties as much as possible).

In Objective C, if you want to share initialization logic between multiple init methods, you can just define a common "setup" method that does all the shared stuff and call it from both intializers:

- (instancetype) init {
  self = [super init];
  if (!self) { return self; }

  [self setup];
  return self;
}

- (instancetype) initWithCoder:(NSCoder *)aDecoder {
  self = [super initWithCoder:aDecoder];
  if (!self) { return self; }

  [self setup];
  return self;
}

- (void) setup {
  self.name = @"Foo";
}

Not gonna happen in swift. The problem is that in both initializers, we're calling [super init] before assigning a value to self.name, which is not okay in swift land. We also can't move the call to self.setup above the call to super.init(), because you're not allowed to reference self until after the class is fully initialized by calling super.init().

So, how to get this chicken out of the egg and onto the plate? Well, we can't call a method on self until after inititialization, but we can call another init, so long as we're calling it from a "convienience" initializer. It's probably easier just to explain by example:

class FooViewController: UIViewController {  
  let name: String

  init(_ coder: NSCoder? = nil) {
    name = "Bar"

    if let coder = coder {
      super.init(coder: coder)
    } else {
      super.init(nibName: nil, bundle:nil)
    }
  }

  required convenience init(coder: NSCoder) {
    self.init(coder)
  }
}

We added an optional NSCoder parameter to our designated initialzer and default it to nil, so we can still call it without any params like before. But the requred init(coder:) initializer from the NSCoding protocol is now marked with convenience, which means it can call the designated initializer and pass in the coder.

In the designated init, we check to see if coder is non-nil (the if let coder = coder conditional) and if so, call super.init(coder:). If it is nil, we do what we would have done originally and call super.init(nibName: nil, bundle: nil).

Now the compiler is happy that we're assigning values to our properties before calling super.init() and we can keep our initialization logic in one place. If we want to use our View Controller in a Storyboard the framework will call init(coder:), and if we want to create one programmatically, we can just say let fooVC = FooViewController().