IBOutlet 为 nil,但它在故事板中已连接,Swift

IBOutlet is nil, but it is connected in storyboard, Swift

使用 Swift 1.1 和 Xcode 6.2。

我有一个包含单个自定义 UIViewController 子类的 UIStoryboard。在它上面,我有一个 @IBOutlet 类型的 UIView 连接,从该控制器到故事板上的 UIView 子类 。对于该视图的子视图,我也有类似的出口。见图A.

但在 运行 时,这些属性为零(图 B)。尽管我已经确定我已经在 Interface Builder 中连接了插座。

想法:

我尝试过的东西:

图A*

图B

*Figure A中的遮蔽代码为:

@IBOutlet private var annotationOptionsView: UIView!
@IBOutlet private var arrivingLeavingSwitch: UISegmentedControl!

谢谢。

通常发生这种情况是因为您的视图控制器尚未加载其视图层次结构。视图控制器仅在某些东西向它发送 view 消息时加载其视图层次结构。系统在实际将视图层次结构显示在屏幕上时执行此操作,这发生在 prepareForSegue:sender:viewWillAppear: 返回之后。

由于您的 VC 尚未加载其视图层次结构,因此您的插座仍然为零。

您可以通过说 _ = self.view 来强制 VC 加载其视图层次结构。

您是从 Storyboard 或 NIB 实例化您的视图控制器,还是通过初始化器直接实例化它?

如果您直接使用初始化程序实例化 class,则不会连接插座。 Interface Builder 创建您的 classes 的自定义实例,并将这些实例编码到 NIB 和 Storyboard 中以进行重复解码,它并不定义 classes 本身。如果这是您的问题,您只需更改创建控制器的代码,改为使用 UIStoryboard 或 UINib 上的方法。

故事板无法识别我添加到其中的任何其他 UI 内容。在 运行 时间所有引用都是零。所以我清除了我的派生数据文件夹,然后这些连接再次工作。

你试过了吗运行产品>清洁。为我解决了一个非常相似的问题。

  1. select .h.m 查看控​​制器文件
  2. 删除那些文件的引用
  3. 将文件重新添加到您的项目树
  4. 打开故事板,最终重新构建项目

我最近遇到了这个问题!这是我的想法。 问题不在于您的情节提要或任何 link 问题。它是关于你如何开始你的 ViewController。特别是当你使用 Swift 时。(当你创建一个 class 文件时,编辑器中几乎什么都没有)

通过简单地使用 super class 中的 init() 无法启动您使用故事板工作的任何内容。所以你需要做的是改变 ViewController 的初始化。代替 let XXViewController = XXViewController() 经过 let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController 这告诉程序去故事板找到 XXViewController 并启动故事板中的所有 IBOutlet

希望对您有所帮助~ GL

我的自定义集合视图单元格发生了这种情况。结果我不得不用 registerNib 替换我的 registerClassforReuseIdentifier 方法。这为我修好了。

检查您的 IBOutlet 连接是否连接到文件所有者或视图。 可能有错误。

其他情况:

在视图控制器的视图实际实例化之前,您的插座不会被设置,在您的情况下,这可能发生在 initWithNibName:bundle 之后不久:—此时它们仍然为零。您所做的任何涉及这些插座的设置都应该在您的视图控制器的 -viewDidLoad 方法中进行。

对我来说,这发生在我不小心将视图控制器的 class 声明为

class XYZViewController: UINavigationController {
}

(即 UINavigationController 而不是 UIViewController)。

Xcode 没有注意到这个错误,class 似乎构建良好,并覆盖了 viewDidLoadviewWillAppear 等函数。正常工作。但是 IBOutlet 中的 none 已连接。

将声明更改为

class XYZViewController: UIViewController {
}

完全修复它。

你可以调用controller.view强制加载视图来初始化IBOutlets,然后你就可以赋值了。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "identifier") {
        let controller = segue.destinationViewController as! YourController
        let _ = controller.view //force to load the view to initialize the IBOutlets

        controller.your_IBOutlet_property = xxx
        ...
        controller.delegate = self
    }
}

这发生在我身上是因为我不小心直接实例化了我的视图控制器,而不是通过故事板实例化它。如果您直接通过 MyViewController() 实例化,则不会连接插座。

就我而言,这是因为我重写了 ViewController 子类中的 loadView 方法,但忘记添加 [super loadView]

-(void)loadView {
// blank
}

当您覆盖 loadView 方法时,您有责任初始化您的子视图。由于您覆盖了它,来自界面构建器的视图没有机会转换为 cocoa 对象,因此出口保持为零。

如果您在视图控制器子类中实现了 loadView,那么您有责任将 storyboard/xib 中的 UI 元素加载到代码中。

或直接致电

[super loadView];

这样超类就有机会将 storyboard/xib 加载到代码中。

对于Swift 3.

func configureView() {
    let _  = self.view
}

我看你用的是ViewController!?在 ViewController class 中,您 必须 使用 -viewDidLoad 而不是 -awakeFromNib-awakeFromNib 用于 UIView class

对我来说,我在本地化故事板上遇到了同样的错误,一个元素被添加到某个区域而不是另一个区域,所以当切换到缺少的元素区域时我对该元素有空引用,我不得不删除使用 .

对该故事板进行(冗余)本地化

您需要先加载视图层次结构,以便在情节提要中实例化插座。为此,您可以手动调用 loadView 或 loadViewIfNeeded 方法。

不小心 我用 AVPlayerViewController 而不是 UIViewController 对我的视图控制器进行了子类化。通过将它重播到 UIViewController 一切恢复正常。这应该有所帮助。

No build cleaning (normal&full), removing derived data folders and quitting Xcode worked for me.

复制 class(链接到 xib)以与另一个 viewcontroller class(链接到故事板)重用后,我遇到了同样的问题。 我忘了删除

override var nibName

override var nibBundle

方法。

移除它们后,我的插座开始工作了。

对我来说,这是崩溃,因为 containerView 是零。

这是我的代码 崩溃

@IBOutlet private var containerView: UIView!  // Connected to Storyboard
override open func loadView() {
    containerView.addSubview(anotherView)
}

缺少的东西是调用 super.loadView()。所以添加它解决了我的问题。

固定码:

@IBOutlet private var containerView: UIView!
override open func loadView() {
    super.loadView()
    containerView.addSubview(anotherView)
}

我之前在 Storyboard 中定义标识符后为自定义单元格添加 register(_:forCellReuseIdentifier:) 时遇到了类似的问题。在 viewDidLoad() 函数中有此代码。一旦我删除它,它就可以正常工作。

我刚刚 运行 遇到的另一个案例。我为 UIViewController 更改了 class 的名称,但我忘记更改构建界面的 .xib 文件的名称。

一旦我发现了这个并使文件名反映了 class 名称,一切都很好!

我希望对某人有所帮助。

还有一个...

如果您有自定义的 class UITableViewCell 但忘记在单元格的样式中指定自定义。

检查是否有任何缺失或断开的插座。

您可以验证是否加载了视图。

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}

如果您有两个 main.storyboards 而您正在更改错误的一个,则可能会发生这种情况。任何时候从未实例化的 storyboard 连接插座时都可能发生这种情况。

如果您以编程方式实例化view controller。然后 尝试像下面这样创建它

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC

而不是直接

let initialVC = InitialVC()

这对我有用。

就我而言,应用程序突然开始崩溃。 调试它发现在viewDidLoad()时所有网点仍然是nil

我的应用程序仍然对大多数视图控制器使用 nibs(不是故事板)。一切就绪,所有插座接线正确。我仔细检查了。

我们通常将我们的视图控制器实例化为

let newVC = MYCustomViewController()

...出于某种原因,只要 .xib 与视图控制器 class 的名称相同,它似乎就可以工作(不过不确定它是如何工作的。我们是 not 使用 nil 参数调用 init(nibName:bundle:),或者覆盖 init() 以在 self 上这样做,就像通常建议的那样...)。

所以我试图显式调用

 let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)

...只会遇到运行时异常错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/nicolasmiari/Library/Developer/CoreSimulator/Devices/3DA3CF21-108D-498F-9649-C4FC9E3C1A8D/data/Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (loaded)' with name 'MYCustomViewController''

然后然后,我看到了:

未选中 .xib 文件的 "Target Membership" 复选框。


一定是在解决与 Xcode 项目文件有关的频繁合并冲突之一时发生的。

Apple 绝对 需要提出一种对 SCM 更友好的项目文件格式。

100% 从没有故事板的 XIB 创建 ViewControllers 的工作解决方案

  1. 创建 class 自定义视图控制器:UIViewController
  2. 创建视图CustomViewControllerView.xib
  3. 在 Interface Builder CustomViewControllerView.xib 中 select 占位符 -> 文件所有者
  4. 在 "Attributes inspector" 中将 Class 设置为 CustomViewController
  5. 在 "Connections inspector" 中将 "view" 连接到 xib 的顶层视图(确保顶层视图的 Class 没有指向 CustomViewController)
  6. 在"Connections inspector"连接其他插座(如果needed/exist)
  7. 在父视图中创建 CustomViewController 实例 controller/App 委托

7.1.

// creating instance
let controller = CustomViewController()

7.2.

// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)

7.3.

// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")

2019 年,这个可怕问题的一种可能性:

  • 假设您可能有一个显示某种时钟的容器视图。所以你有

    class时钟:UIViewController

您实际上在应用程序的许多地方使用它

在主界面,在详情界面,在编辑界面。

您有一个类似 snapchat 的复杂现代应用程序。

事实上,Clock 实际上可能 同一时间 加载 不止一次 =]同屏。 (也许它在某些情况下是隐藏的。)

您开始在众多情节提要之一上处理 Clock 的一个实例。

在该故事板上添加标签 NewLabel。

自然地,您在代码中添加插座。一切都应该工作。所有其他网点都运行良好。

肯定链接了插座。

但是应用程序崩溃,NewLabel 为 nil。

Xcode 清楚地告诉你“你忘了连接插座”。

原因是............你只有 一个 的故事板使用时钟!

崩溃实际上来自>>>另一个地方<<<<你正在使用时钟!!!!

Xcode 没有告诉你崩溃是从另一个地方发生的,没有 从你工作的地方!

崩溃实际上不是来自您工作的地方 - 它来自 另一个 故事板,该故事板上没有“NewLabel”项目!!!

令人沮丧。

如果您有两个 storyboards/xibs,继承层次结构中每个 'class level' 一个,必须在每个 'class level' 中定义出口,并在需要对其进行操作的 class 中引用.在我的例子中,它是父 class.