【问题标题】:Why UIViewController is created from same name XIB even though empty constructor is used?为什么 UIViewController 是从同名 XIB 创建的,即使使用了空构造函数?
【发布时间】:2021-09-03 01:15:54
【问题描述】:

我有以下课程

CalendarViewController.swift

import UIKit

class CalendarViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
}

我有CalendarViewController.xib,文件所有者自定义类是CalendarViewController

基于https://stackoverflow.com/a/55801259/72437

我想如果我想从 XIB 创建视图控制器,我需要执行

extension UIViewController {
    static func instanceFromNib() -> Self {
        func instantiateFromNib<T: UIViewController>() -> T {
            return T.init(nibName: String(describing: T.self), bundle: nil)
        }

        return instantiateFromNib()
    }
}

let calendarViewController = CalendarViewController.instanceFromNib()

但是,如果我尝试以下代码

let calendarViewController = CalendarViewController()

我注意到calendarViewController 是从XIB 创建的! (因为它包含了来自 XIB 的所有 UI 组件)


我还注意到,如果我从项目中删除 CalendarViewController.xib 并运行相同的代码

let calendarViewController = CalendarViewController()

同样,视图控制器不会从 XIB 创建。


我可以知道,为什么UIViewController 是从同名XIB 创建的,即使使用了空构造函数?

【问题讨论】:

  • 因为init(name:bundle)nil 名称会在某个时候调用默认的init(),并查看developer.apple.com/documentation/uikit/uiviewcontroller/… 的文档或者它甚至在init(name:bundle:) 中进行了描述
  • 但这并不能解释为什么init会从“CalendarViewController.xib”读取,因为字符串值“CalendarViewController.xib”没有传递给init
  • 如果 UIViewController 的 init 实际上是 init{ return [super initWithNibName:nil: bundle: nil];} 怎么办?

标签: ios swift


【解决方案1】:

CalendarViewController.init() / CalendarViewController() 内部调用 - init(nibName: String?, bundle: Bundle?)

很明显,您没有为nibName 指定任何值。所以nibName 值在你的情况下是nil

让我们继续阅读UIViewController.init(nibName:bundle:) 文档。 讨论中的这一部分是我们感兴趣的。

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

  1. nibName 在你的情况下是 nil
  2. 您尚未在子类中为 loadView() 添加任何实现。

这将我们引向UIViewController.nibName docs -

讨论

此属性包含在初始化时为init(nibName:bundle:) 方法指定的值。该属性的值可能是nil

如果您使用 nib 文件来存储视图控制器的视图,建议您在初始化视图控制器时明确指定该 nib 文件。但是,如果您没有指定 nib 名称,并且没有覆盖自定义子类中的 loadView() 方法,则视图控制器会使用其他方式搜索 nib 文件。具体来说,它会查找具有适当名称(不带 .nib 扩展名)的 nib 文件,并在请求其视图时加载该 nib 文件。具体来说,它会(按顺序)查找具有以下名称之一的 nib 文件:

如果视图控制器类名以单词“Controller”结尾,如在 MyViewController 中,它会查找名称与类名匹配但不包含单词“Controller”的 nib 文件,如 MyView.nib。

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

关键是 - 如果您没有为 nibName 指定任何内容并且您没有为您的 UIViewController 子类实现 loadView() - 系统会自动尝试在应用程序包资源中查找匹配的 nib 文件。

  1. 如果找到,它会将视图附加到您的 UIViewController.view 实例。
  2. 如果找不到,它会创建一个空的 UIView 实例并将该视图附加到您的 UIViewController.view 实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 2021-01-26
    相关资源
    最近更新 更多