子类化 FUIAuthPickerViewController 时“无法加载 NIB”

Posted

技术标签:

【中文标题】子类化 FUIAuthPickerViewController 时“无法加载 NIB”【英文标题】:"Could not load NIB" when subclassing FUIAuthPickerViewController 【发布时间】:2017-05-06 06:55:49 【问题描述】:

我能在网上找到的唯一相关问题是 GitHub 上的问题报告: https://github.com/firebase/FirebaseUI-ios/issues/128

但是,似乎没有任何解决方案。

使用 FirebaseUI,我想对 FUIAuthPickerViewController 进行子类化,以便对其进行一些自定义。当我继承并调用FUIAuth.defaultAuthUI!.authViewController 时,我得到以下运行时异常:

'NSInternalInconsistencyException',原因:'无法在包中加载 NIB

我是 Swift 新手,所以很可能我错误地将 FUIAuthPickerViewController 子类化,但我在网上阅读的所有内容都表明并非如此。

这是我的子类:

import UIKit
import FirebaseAuthUI

class AuthViewController: FUIAuthPickerViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
    


这是我的代表:

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)
    

如果我删除默认的 FUIAuthPickerViewController 一切正常。我只是假设如果未定义子类,子类将从其父类继承其 NIB。

感谢任何帮助。

问候, 科恩

【问题讨论】:

【参考方案1】:

事实证明,这是 FirebaseUI 中的一个错误,它从旧版本中重新出现。

问题可以here追踪。

临时解决方案是在您的 FUIAuthPickerController 子类中硬编码正确的 NIB 名称:

斯威夫特:

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()
    


目标-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

【讨论】:

【参考方案2】:

FUIAuthPickerViewControllerUIViewController

The init documentation 表示:

如果为 nibName 参数指定 nil 并且不覆盖 loadView() 方法,则视图控制器会按照 nibName 属性中的说明搜索 nib 文件。

The nibName documentation 说:

具体来说,它会查找具有适当名称的 nib 文件 (没有 .nib 扩展名)并在其视图时加载该 nib 文件 被要求。具体来说,它会(按顺序)查找 nib 文件 以下名称之一:

    如果视图控制器类名称以单词“Controller”结尾,如在 MyViewController 中,它会查找名称与 不带“Controller”一词的类名,如 MyView.nib。

    它查找名称与视图控制器类的名称匹配的 nib 文件。例如,如果类名是 MyViewController, 它会查找 MyViewController.nib 文件。

这里没有任何迹象表明它会检查所有超类的名称以查找 nib。我假设它正在检查“AuthView.nib”和“AuthViewController.nib”,然后放弃。

【讨论】:

这是有道理的,如果是这样的话,FirebaseUI 文档对这个过程非常模糊,说你需要做的就是子类化并实现一个委托方法。【参考方案3】:

这似乎也是由 FirebaseUI 上的错误引起的,我遇到了同样的问题并实施了几个解决方案,但它仅在我将 pod 从 Firebase 4.1.0 更新到 Firebase 4.1.1 后才有效。

此 git repo 还声称该错误已在此更新中修复。

您可以通过以下方式查看当前的版本: 在项目路径位置的终端中的“pod search FirebaseUI”,如果它不是最新版本,只需执行“pod update”,这有望解决问题。

【讨论】:

以上是关于子类化 FUIAuthPickerViewController 时“无法加载 NIB”的主要内容,如果未能解决你的问题,请参考以下文章

CAsyncSocket 没有子类化?

子类化导航控制器有啥用? [关闭]

麻烦子类化 SCNScene

UIViewController 的 Swift 子类化子类

子类化 UIAlertController

子类化 UItableViewCell 选择