IBOutlet为零,但已在情节提要中连接到Swift


102

使用Swift 1.1和Xcode 6.2。

我有一个包含单个自定义UIViewController子类的UIStoryboard 。在它上面,我有一个从该控制器到情节提要上的子类@IBOutlet的类型连接。对于该视图的子视图,我也有类似的渠道。见图A。UIViewUIView

但是在运行时,这些属性为零(图B)。即使我确信已经连接了Interface Builder中的插座。

想法

  • 是否有可能因为我正在使用子类的子类而使初始化混乱?我没有覆盖任何初始化程序
  • awakeFromNib: 由于某种原因没有被打电话
  • 也许它没有连接到子视图上的子视图

我尝试过的事情:

  • @IBOutlet完全匹配和情节提要的项目类型(而不是UIView
  • 删除属性和出口并重新添加它们

图A

图A *

图B

图B

*中的模糊代码Figure A为:

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

谢谢。


为什么不改变!至 ?

clearView为nil,是因为未链接到情节提要(请参见代码左侧的带孔的圆圈,表示未链接),在屏幕截图中看不到注解OptionView的声明。
Javier Flores Font

@JavierFloresFont:clearView我希望是零。这是我尚未重构的事情。另请参见图A的脚注。@ShaanSingh应该是!因为来自情节提要的连接是(应该)在运行时设置的,因此不应为零。
Stefan Arambasich

该视图控制器如何加载?向我们显示要求它的代码,或描述连接到它的序列。
rob mayoff

1
它正在获得正确的故事板: let vc = UIStoryboard(name: "LocationPickerModal", bundle: nil) .instantiateViewControllerWithIdentifier("LocationPickerModalViewController") as LocationPickerModalViewController
Stefan Arambasich 2015年

Answers:


146

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

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

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


4
这是在viewWillAppear:被调用时发生的,这是我第一次使用该插座执行任何操作。访问视图对我没有任何帮助。还是零。
Stefan Arambasich

谢谢!这也为我工作。var v = viewcontroller.view; 强制加载视图层次结构。不错的小把戏!;)
Yordi Uytersprot

@YordiUytersprot您将把这行放在哪里?
Async-

4
好吧,如果您实例化一个viewcontroller:让vc = self.storyboard?.instantianteViewControllerWithIdentifier(“ StoryboardIDfromVC”)为?CustomVC; 让view = vc.view; //现在,您可以在此处从CustomVC访问IBOutlets。希望对您有帮助!:)
Yordi Uytersprot

4
UIViewcontroller.loadViewIfNeeded()是在这里使用的正确方法。
Orkoden

27

您是否尝试过运行产品>清洁。为我解决了一个非常类似的问题。


是的 抱歉,是要标记我的答案。它仅在删除DerivedData项目文件夹后才开始工作。
Stefan Arambasich 2015年

3
在我的视图层次结构中间,只有两个出口为零。产品->清洁对我有用!
Rikco 2015年

1
obj c,只是清理项目对我有用...无法相信花了一个多小时,甚至都没有想到要清理项目:
温室

只是Product-> Clean不适用于我,但是我启动了一个不同的模拟器,它也起作用了,因此DerivedData文件夹中也一定有问题。
endavid

22

您是从情节提要或NIB实例化视图控制器,还是直接通过初始化程序将其实例化?

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


2
我正在创建一个UIStoryboard实例并对其进行调用instantiateViewControllerWithIdentifier
Stefan Arambasich

15

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


2
这就是答案。我为此战斗了一段时间,清理了构建文件夹和所有内容。在我的情况下,viewDidLoad()所有连接都建立了,但viewWillAppear()几乎所有连接都建立了nil(有时仍连接一两个)。我尝试了一切,最后删除了派生的数据文件夹,进行了重建,一切都很好。
ruttopia

6
即使3年后,Xcode 9.2仍然存在相同的错误。非常感谢。
凯末尔·坎·凯纳克

1
在此报告Xcode 11中仍然存在。:(
花了

13

我的自定义集合视图单元格正在发生这种情况。原来我不得不用registerNib替换registerClassforReuseIdentifier方法。这为我解决了。


你是对的。我详细阅读了Swift编程语言中的ARC计数内容。我找不到原因,为什么IBOutlet弱属性仍然为零。最后,我用Google搜索“ @IBOutlet swift nil”,然后在SO中找到您的答案。然后,我标记了在viewDidLoad中添加了“ self.collectionView!.registerClass”的Xcode模板行。然后,它起作用。你救了我的命。
charles.cc.hsu 2016年

12

之所以发生这种情况,是因为我不小心直接实例化了我的视图控制器,而不是通过情节提要实例化了它。如果直接通过实例化,MyViewController()则插座将不会连接。


如果您使用XIB文件,直接实例化仍然可以成功进行。
Luat Vu Dinh

11

就我而言,发生这种情况是因为我loadView在ViewController子类中重写了该方法,但是却忘记了添加[super loadView]

-(void)loadView {
// blank
}

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

如果在视图控制器子类中实现loadView,那么将UI元素从情节提要/ xib加载到代码中就成为您的责任。

或者只是打电话

[super loadView];

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


8

您可以调用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
    }
}

7

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

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

而不是直接

let initialVC = InitialVC()

这对我有用。


6

对我来说,这是由于我不小心将视图控制器的类声明为

class XYZViewController: UINavigationController {
}

(即UINavigationControllerUIViewController)。

Xcode中没有拿起这个错误,类似乎构建的罚款,并覆盖功能,如viewDidLoadviewWillAppear等一切工作正常。但是没有IBOutlet s连接。

将声明更改为

class XYZViewController: UIViewController {
}

完全修复。


5

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

仅使用init()from超级类无法启动您使用故事板工作的任何内容。因此,您需要做的是更改ViewController的初始化。替换 let XXViewController = XXViewController()let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController 告诉程序进入情节提要板中找到XXViewController并IBOutlet在您的情节提要板中初始化所有内容。

希望对您有帮助〜GL


那不是问题
Stefan Arambasich

4

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

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

    时钟类:UIViewController

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

在主屏幕上,在详细信息屏幕上,在编辑屏幕上。

您有一个复杂的,像手套一样的现代应用程序。

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

您开始处理一个实例 Clock多个情节提要板之一中的。

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

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

肯定有链接了出口。

但是该应用因NewLabel而崩溃为零。

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

原因是.......... 在Clock的情节提要中只有一种使用“ NewLabel” !

崩溃实际上是从>>>其他地方<<<<您正在使用Clock !!!!!

Xcode 不会告诉您崩溃完全来自另一个地方,而不是您工作的地方!

崩溃实际上并非来自您的工作场所,而是来自另一个情节提要,该情节提要上没有“ NewLabel”项!

令人沮丧


3

对于Swift 3。

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

2

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


2

以我为例,该应用突然开始崩溃。调试它表明,所有网点仍然nil在时间viewDidLoad()

我的应用程序仍然对大多数视图控制器使用笔尖(而不是情节提要)。一切就绪,所有插座均已正确布线。我仔细检查了。

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

let newVC = MYCustomViewController()

...由于某种原因,似乎工作,只要的.xib被命名为相同视图控制器类(不知道如何工作的。我们调用init(nibName:bundle:)与零的参数,或者重写init()这样做就self喜欢它通常建议...)。

所以我试图明确地打电话

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

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

***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无法在捆绑包中加载NIB:'NSBundle </ Users / nicolasmiari / Library / Developer / CoreSimulator / Devices / 3DA3CF21-108D-498F-9649-C4FC9E3C1A8D / data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app>(已加载)',名称为“ MYCustomViewController”

随后,我看到它:

.xib文件的“目标成员身份”复选框未选中。


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

苹果肯定需要提出一种对SCM更友好的项目文件格式。


2

在没有StoryBoards的情况下从XIB创建ViewController的100%工作解决方案

  1. 创建类CustomViewController:UIViewController
  2. 创建视图CustomViewControllerView.xib
  3. 在Interface Builder的CustomViewControllerView.xib中,选择“占位符”->“文件所有者”
  4. 在“属性检查器”中,将“类”设置为CustomViewController
  5. 在“连接检查器”中,将“视图”连接到xib的顶级视图(确保顶级视图的类未指向CustomViewController)
  6. 在“连接检查器”中,连接其他插座(如果需要/存在)
  7. 在父视图控制器/应用程序委托中创建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")

很棒的答案,谢谢!对于它的价值,您还可以直接在CustomViewController类中重写init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)并调用步骤7.2 self
brandonscript


1

其他情况:

在实际实例化视图控制器的视图之前,不会设置出口,对于您而言,这可能是在initWithNibName:bundle:之后不久发生的,此时它们仍然为零。您所做的任何涉及这些出口的设置都应在视图控制器的-viewDidLoad方法中进行。


1

对我来说,我在本地化的情节提要板上有相同的错误,在某个区域设置中添加了一个元素,而不是在另一个区域中添加了一个元素,因此当切换到缺少的元素区域设置时,该元素具有空引用,因此我必须删除(冗余)本地化使用https://stackoverflow.com/a/42256341/1356559的故事板。


1

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

这是我的Crash代码。

@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)
}

您不应该永远不直接调用loadView()(developer.apple.com/documentation/uikit/uiviewcontroller/…),而是调用self.view
Lio

1

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


1

我遇到了另一个案例。我为UIViewController更改了类的名称,但是我忘记更改了构建接口的.xib文件的名称。

一旦发现了这个问题,并让文件名反映了类名,那就太好了!

希望对您有所帮助。


1

还有一个...

如果您具有UITableViewCell的自定义类,但是忘记在单元格的样式中指定“自定义”。


1

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

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

0
  1. 同时选择.h.m查看控制器文件
  2. 删除这些文件的引用
  3. 将文件重新添加到您的项目树中
  4. 打开情节提要,最终重新构建项目

0

偶然地,我使用AVPlayerViewController而不是将视图控制器子类化UIViewController。通过将其重播到UIViewController正常状态。这应该有所帮助。

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


0

复制一个类(链接到xib)以与另一个viewcontroller类(链接到情节提要)重用后,我遇到了同样的问题。我忘了删除

override var nibName

override var nibBundle

方法。

卸下它们后,我的店铺开始工作。




0

如果您有两个,main.storyboards并且正在更改错误的一个,则可能会发生。当您连接来自非实例化的插座时,可能会发生这种情况storyboard

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.