IBOutlet 是空的,但它是在故事板中连接的,Swift

使用 Swift 1.1和 Xcode 6.2。

I have a UIStoryboard containing a singular, custom UIViewController subclass. On it, I have an @IBOutlet connection of type UIView from that controller to a UIView 子类 on the storyboard. I also have similar outlets for subviews of that view. See figure A.

但是在运行时,这些属性是 nil (图 B)。尽管我已经保证我已经连接了 Interface Builder 的电源插座。

思想 :

  • 有没有可能因为我使用了一个子类的子类,所以初始化过程出了问题?我没有重写任何初始化程序
  • 由于某种原因 awakeFromNib:没有接到电话
  • 也许它没有连接到子视图上的子视图

我尝试过的事情:

  • 完全匹配 @IBOutlet和故事板项目类型(而不是 UIView)
  • 删除属性和插座并重新添加它们

Figure A

图 A *

Figure B

图 B

* Figure A中模糊的代码是:

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

Thank you.

92002 次浏览

通常发生这种情况是因为视图控制器尚未加载其视图层次结构。视图控制器只有在发送 view消息时才加载其视图层次结构。当需要在屏幕上实际显示视图层次结构时,系统会这样做,这发生在 prepareForSegue:sender:viewWillAppear:返回之后。

Since your VC hasn't loaded its view hierarchy yet, your outlets are still nil.

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

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

如果直接使用初始值设定项实例化类,则不会连接出口。Interface Builder 创建类的定制实例,并将这些实例编码到 NIBs 和情节串连板中以便重复解码,但它并不定义类本身。如果这是您的问题,那么您只需要更改创建控制器的代码,以使用 UIStoryboard 或 UINib 上的方法。

情节串连图板不能识别我添加到其中的任何进一步的 UI 内容。在运行时,所有引用都为零。所以我清除了派生数据文件夹,然后这些连接再次工作。

你有没有试过运行 Product > Clean。为我解决了一个非常类似的问题。

  1. 选择 .h.m视图控制器文件
  2. 删除那些文件的引用
  3. 将文件重新添加到项目树中
  4. 打开故事板,最终重建项目

我最近遇到了这个问题! 这是我的想法。 这个问题不是关于你的故事板或任何链接的问题。它是关于如何启动 ViewController 的。特别是当你用斯威夫特的时候。(创建类文件时,编辑器中几乎没有任何内容)

通过简单地使用 init()从超级类不能启动任何你与故事板一起工作。因此,您需要做的是更改 ViewController 的初始化。替换 let XXViewController = XXViewController() 作者 let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController This tells the program to go to the storyboard find XXViewController and initiates all IBOutlet in your storyboard.

希望这有帮助 ~ GL

这发生在我的自定义收集视图单元格上。原来我必须用 registerNib 替换 registerClassforReuseIdentifier 方法。这就解决了我的问题。

检查 IBOutlet 连接是否连接到 File 所有者或视图。 There could be mistakes.

其他情况:

直到视图控制器的视图实际实例化之后,才会设置出口,在您的例子中,这可能发生在 initWithNibName: bundle: ー之后不久,此时它们仍然为 nil。任何涉及到这些出口的设置都应该发生在视图控制器的-viewDidLoad 方法中。

For me, this occurred when I accidentally declared my view controller's class as

class XYZViewController: UINavigationController {
}

(ie as a UINavigationController not a UIViewController).

Xcode 没有发现这个错误,类似乎构建得很好,并且覆盖了诸如 viewDidLoadviewWillAppear等函数,所有这些函数都能正常工作。但是所有的 IBOutlet都没有连接。

将声明更改为

class XYZViewController: UIViewController {
}

完全修好了。

可以调用 controller.view强制加载视图以初始化 IBOutlet,然后就可以分配值。

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方法时,您的责任是初始化子视图。由于你覆盖了它,来自 Interface Builder 的视图就没有机会转换成可可对象,因此出口仍然为零。

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

或者直接打电话

[super loadView];

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

For Swift 3.

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

我看到你使用 ViewController! ? 在 ViewController类你 必须的使用 -viewDidLoad没有 -awakeFromNib-awakeFromNib用于 UIView

对我来说,我在本地化的故事板上也有同样的错误,一个元素是在某个地区添加的,而不是在另一个地区,所以当切换到缺少的元素地区时,我对该元素的空引用,我必须使用 https://stackoverflow.com/a/42256341/1356559删除(多余的)故事板的本地化。

您需要首先加载视图层次结构,以便在故事板中实例化出口。为此,可以手动调用 loadView 或 loadViewIfNeeded 方法。

偶然地 我用 AVPlayerViewController而不是 UIViewController子类化了我的视图控制器。通过重播到 UIViewController,一切恢复正常。这个应该有用。

没有构建清理(正常和完整) ,删除派生数据文件夹和退出 Xcode 为我工作。

在复制了一个类(链接到 xib)并将其与另一个 viewcontroller 类(链接到故事板)重用之后,我遇到了同样的问题。 我忘记拿了

override var nibName

还有

override var nibBundle

方法。

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

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

Here is my code with 克拉舍.

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

The missing thing was calling the super.loadView(). So adding it solved problem for me.

固定代码 :

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

在我已经在故事板中定义了标识符之后,之前为自定义单元格添加了 register (_: forCellReuseIdentifier:)时,我遇到了类似的问题。在 viewDidLoad ()函数中有这段代码。一旦我把它取出来,就没问题了。

我又碰到一个案子。我为 UIViewController 更改了类的名称,但是忘了更改。构建接口的 xib 文件。

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

我希望这能帮到别人。

还有一个。

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

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

enter image description here

You can validate if the is view is loaded.

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

如果你有两个 main.storyboards,并且你正在对错误的 main.storyboards进行修改,这种情况就会发生。这可能发生在任何时候,您连接一个插座从一个未实例化的 storyboard

如果以编程方式实例化 view controller,则 try creating it like below

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

而不是直接

let initialVC = InitialVC()

这招对我很管用。

在我的情况下,应用程序突然开始崩溃。 调试显示,所有的网点仍然是 nil时的 viewDidLoad()

我的应用程序仍然使用 尼布斯(而不是故事板)为大多数视图控制器。一切都准备就绪,所有的插座都接好了。我又查了一遍。

We typically instantiate our view controllers as

let newVC = MYCustomViewController()

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

So I tried to explicitly call

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

... 只会出现运行时异常错误:

* * * 由于未捕获异常导致终止应用程序“ NSInternalInconcencyException”,原因: “无法在 bundle 中加载 NIB: “ NSBundle < /Users/nicolasmiari/Library/Developer/CoreSimulator/Device/3DA3CF21-108D-498F-9649-C4FC9E3C1A8D/data/Container/Bundle/Application/C543DCDC1-AE86-4D29-988C-9CCE89E23543/MyApp.应用程式 > (载入)」 ,名称为「 MYCustomViewController 」

那么,我看到了:

没有选中. xib 文件的“ Target Membership”复选框。


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

苹果 当然需要提出一个更加 SCM 友好的项目文件格式。

100% 工作解决方案创建查看器从 XIB 没有故事板

  1. 创建类 CustomViewController: UIViewController
  2. 创建视图 CustomViewControllerView.xib
  3. 在 CustomViewControllerView.xib Interface Builder 中选择占位符-> 文件的所有者
  4. In "Attributes inspector" set Class to CustomViewController
  5. 在“连接检查器”中,将“视图”连接到 xib 的顶层视图(确保顶层视图的 Class 不指向 CustomViewController)
  6. 在“连接检查器”中连接其他插座(如果需要/存在)
  7. 在父视图控制器/App 委托中创建 CustomViewController 的实例

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年,这个可怕问题的一种可能性是:

  • 假设您有一个显示某种时钟的容器视图

    类时钟: UIViewController

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

在主屏幕上,在细节屏幕上,在编辑屏幕上。

You have a complicated snapchat-like modern app.

事实上,Clock实际上可能是在 同一个屏幕上的某个地方的 same time上加载 不止一次。(也许它隐藏在某些情况下。)

您开始在众多情节串连板中的一个上处理 Clock的一个实例。

在故事板上添加一个标签,NewLabel。

当然,你可以在代码中添加插座,所有的插座都可以正常工作,其他的插座都可以正常工作。

You have 当然 linked the outlet.

But the app crashes with 新标签 as nil.

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

原因是这个... ... 你有“新标签”只有 的故事板使用的时钟!

崩溃实际上是从 >>> an other place <<<<你正在使用的时钟!

Xcode does not告诉你的崩溃是从 另一个的地方共同,没有从你工作的地方!

崩溃实际上不是从你工作的地方-它是从 另一个故事板,在那里没有“新标签”的项目在该故事板! ! !

真令人沮丧。

如果您有两个故事板/xibs,在继承层次结构中每个“类级别”都有一个,那么必须在每个类中定义出口,并在需要对其进行操作的任何类中引用它。对我来说,是家长课。