"Could not load NIB" when subclassing FUIAuthPickerViewController

802 views Asked by At

The only related issue I could find online was an issue report on GitHub: https://github.com/firebase/FirebaseUI-iOS/issues/128

However, there didn't seem to be any resolution.

Using FirebaseUI, I'd like to subclass FUIAuthPickerViewController so I can customize it a little. When I subclass and call FUIAuth.defaultAuthUI!.authViewController, I get the following runtime exception:

'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle

I'm new to Swift, so it's very possible I'm incorrectly subclassing FUIAuthPickerViewController, but everything I've read online points toward that not being the case.

Here's my subclass:

import UIKit
import FirebaseAuthUI

class AuthViewController: FUIAuthPickerViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

Here's my delegate:

public class AuthManager: NSObject, FUIAuthDelegate {
    // TODO: Implement TOS URL
    // TODO: Implement custom strings for multiple languages

    static let instance = AuthManager()
    private override init() {
        super.init()

        self.firebaseUI().delegate = self;
        self.firebaseUI().providers = [FUIGoogleAuth(), FUIFacebookAuth()]
    }

    public func firebaseUI() -> FUIAuth {
        return FUIAuth.defaultAuthUI()!
    }

    public func firebase() -> FIRAuth {
        return FIRAuth.auth()!
    }

    public func addStateChangeListener(listener: @escaping FIRAuthStateDidChangeListenerBlock) {
        self.firebase().addStateDidChangeListener(listener)
    }

    public func showLoginFrom(viewController: UIViewController) {
        viewController.present(self.firebaseUI().authViewController(),
                               animated: true,
                               completion: nil)
    }

    // MARK: FUIAuthDelegate

    public func authUI(_ authUI: FUIAuth, didSignInWith user: FIRUser?, error: Error?) {

    }

    public func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController {
        return AuthViewController(authUI: authUI)
    }
}

If I remove the default FUIAuthPickerViewController everything works fine. I just assumed by subclass would inherit its NIB from its parent if one wasn't defined.

Any help is appreciated.

Regards, Cohen

3

There are 3 answers

0
cohenadair On BEST ANSWER

It turns out this is a bug in FirebaseUI that has resurfaced from an older version.

The issue can be tracked here.

A temporary solution is to hardcode the correct NIB name in your FUIAuthPickerController subclass:

Swift:

import UIKit
import FirebaseAuthUI

class AuthViewController: FUIAuthPickerViewController {

    override init(nibName: String?, bundle: Bundle?, authUI: FUIAuth) {
        super.init(nibName: "FUIAuthPickerViewController", bundle: bundle, authUI: authUI)
    }

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

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

Objective-C:

@implementation CustomAuthPickerViewController
...

 - (instancetype)initWithNibName:(NSString *)nibNameOrNil
                         bundle:(NSBundle *)nibBundleOrNil
                         authUI:(FUIAuth *)authUI {

     self = [super initWithNibName:@"FUIAuthPickerViewController"
                           bundle:nibBundleOrNil
                           authUI:authUI];

    if (self) {
        self.title = @"Your Title";
     }

    return self;
} 

...
@end
1
WhatsUpNSDoc On

FUIAuthPickerViewController is a UIViewController.

The init documentation for that class says:

If you specify nil for the nibName parameter and you do not override the loadView() method, the view controller searches for a nib file as described in the nibName property.

The nibName documentation says:

Specifically, it looks for a nib file with an appropriate name (without the .nib extension) and loads that nib file whenever its view is requested. Specifically, it looks (in order) for a nib file with one of the following names:

  1. If the view controller class name ends with the word ‘Controller’, as in MyViewController, it looks for a nib file whose name matches the class name without the word ‘Controller’, as in MyView.nib.

  2. It looks for a nib file whose name matches the name of the view controller class. For example, if the class name is MyViewController, it looks for a MyViewController.nib file.

There's nothing here to suggest it would check the names of all superclasses for nibs. I assume it's checking "AuthView.nib" and "AuthViewController.nib", and then giving up.

0
Arturo Reyes On

This also seems to be caused by a bug on FirebaseUI, I had the same problem and implemented several solutions but it only worked after I did pod update from Firebase 4.1.0 to Firebase 4.1.1.

This git repo also claims that the bug was fixed in this update.

You can see what version you are currently at by doing: 'pod search FirebaseUI' in terminal in your project's path location, if it is not the latest version, just do 'pod update' and this hopefully solves the problem.