2

I am attempting to make a subclass of UINavigationController that takes additional dependencies. I'd also like to be able to create and specify a root view controller upon initialization. I have this code:

init(rootVC: UIViewController, authUser: AppUser) {
    self.authUser = authUser
    super.init(rootViewController: rootVC)
}

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

However, upon attempted initialization, I get this error:

Fatal error: Use of unimplemented initializer 'init(nibName:bundle:)' for class

I've looked at other SO answers, in particular this one, which suggests fixing the problem by also overriding the init(nibName:bundle:) method. However, this means I am not able to properly inject the user dependency. How best to address this issue?

Cognitio
  • 410
  • 1
  • 4
  • 14
  • Why not just create a protocol, the defines the dependencies you need and have your Custom class conform to it. – Rakshith Nandish Jan 07 '18 at 05:17
  • @RakshithNandish How would that help? I would still need to inject the dependencies somehow. Simply declaring protocol conformance does not do any injection. I just declares that the class will have those properties / functions. – Cognitio Jan 07 '18 at 05:20

1 Answers1

2

Have you tried convenience initialization?

convenience init(rootVC: UIViewController, authUser: AppUser) {
    self.init(rootViewController: rootVC)
}

Please, also read this question if you'd go with convenience initialization.

Edit

You can set AppUser this way:

final class Navigation: UINavigationController {

    private(set) var authUser: AppUser!

    convenience init(rootVC: UIViewController, authUser: AppUser) {
        self.init(rootViewController: rootVC)
        self.authUser = authUser
    }
}

Edit

Follow this link.

This is a convenience method for initializing the receiver and pushing a root view controller onto the navigation stack. Every navigation stack must have at least one view controller to act as the root.

iWheelBuy
  • 5,470
  • 2
  • 37
  • 71
  • The problem I run into then is that the init(rootViewController:) initializer is not inherited from the superclass. Presumably this is because of the caveat in the docs: "Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply." Since my dependency does not have a default value, there is no inheritance. If I override it myself, I then get the error "Cannot assign to property, authUser is a let constant" – Cognitio Jan 07 '18 at 05:28
  • @Cognitio I think it is not inherited because it is not a designated initializer. Check the edited answer. – iWheelBuy Jan 07 '18 at 05:36
  • Is it not a designated initializer though? You can call it from a subclass designated initializer, which you shouldn't be able to do if it was a convenience initializer. Your edited solution works, but only by making the dependency an optional (and a variable). I'd really like the dependency to be a constant and to be unable to be set to nil, which makes it much safer. – Cognitio Jan 07 '18 at 05:49
  • Also, if you inherit all the designated initializers of a superclass, then the subclass should inherit all convenience initializers as well as per rule 2: "If your subclass provides an implementation of all of its superclass designated initializers—*either by inheriting them as per rule 1*, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers. These rules apply even if your subclass adds further convenience initializers." – Cognitio Jan 07 '18 at 05:54
  • @Cognitio I just give you some information to think and a workaround, I'm NOT a great professional. I have added one more edit which says that it is a `convenience` initialization – iWheelBuy Jan 07 '18 at 05:57
  • Much appreciated! I'll probably end up using your workaround. I just think it's interesting that this class doesn't seem to follow the rules. ¯\_(ツ)_/¯ – Cognitio Jan 07 '18 at 06:04
  • @Cognitio If you'll find a better way - please post the solution. – iWheelBuy Jan 07 '18 at 06:05