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

时间:2015-03-28 19:09:46

标签: xcode swift uistoryboard null iboutlet

使用Swift 1.1和Xcode 6.2。

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

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

思想

  • 是否有可能因为我正在使用子类的子类,因为初始化会弄乱一些东西?我没有覆盖任何初始化者
  • awakeFromNib:因某种原因未被调用
  • 可能它没有连接到子视图的子视图

我尝试过的事情:

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

Figure A

图A *

Figure B

图B

* Figure A中隐藏的代码是:

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

谢谢。

31 个答案:

答案 0 :(得分:128)

通常会发生这种情况,因为您的视图控制器尚未加载其视图层次结构。视图控制器仅在某些内容向其发送view消息时加载其视图层次结构。系统会在实际将视图层次结构放在屏幕上时执行此操作,这在prepareForSegue:sender:viewWillAppear:之类的事情发生之后就会发生。

由于您的VC还没有加载其视图层次结构,因此您的网点仍为零。

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

答案 1 :(得分:25)

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

答案 2 :(得分:20)

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

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

答案 3 :(得分:15)

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

答案 4 :(得分:11)

我的自定义集合视图单元格发生了这种情况。事实证明我必须用registerNib替换registerClassforReuseIdentifier方法。这为我解决了。

答案 5 :(得分:10)

就我而言,之所以发生这种情况,是因为我在ViewController子类中覆盖了for(int count = 0; count < max_count; count++) { auto t0 = std::chrono::high_resolution_clock::now(); cv::remap(cv_im_gpu, cv_im_gpu_remap, map1_gpu, map2_gpu, CV_INTER_LINEAR); auto t1 = std::chrono::high_resolution_clock::now(); time += t1 - t0; } average_time = time / max_count; 方法,但忘了添加loadView

[super loadView]

当您覆盖-(void)loadView { // blank } 方法时,您有责任初始化子视图。由于您覆盖它,因此界面构建器中的视图无法转换为可可对象,因此出口保持为零。

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

或者只是致电

loadView

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

答案 6 :(得分:8)

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

答案 7 :(得分:7)

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

答案 8 :(得分:6)

对我来说,这是在我意外地将视图控制器的类声明为

时发生的
class XYZViewController: UINavigationController {
}

(即作为UINavigationController而不是UIViewController)。

Xcode没有接受这个错误,该类似乎构建正常,并覆盖viewDidLoadviewWillAppear等功能都正常工作。但是IBOutlet没有一个连接起来。

将声明更改为

class XYZViewController: UIViewController {
}

完全修复了它。

答案 9 :(得分:4)

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

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

希望这有帮助~GL

答案 10 :(得分:3)

对于Swift 3。

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

答案 11 :(得分:1)

对我来说,我在本地化的故事板上有同样的错误,在某些语言环境中添加了一个元素而在另一个语言环境中没有添加,所以当切换到缺少的元素区域设置时,我对该元素有空引用,我不得不删除(冗余)使用https://stackoverflow.com/a/42256341/1356559对该故事板进行本地化。

答案 12 :(得分:1)

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

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

代替直接

let initialVC = InitialVC()

这对我有用。

答案 13 :(得分:1)

用于从没有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")

答案 14 :(得分:1)

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

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

答案 15 :(得分:1)

2019,此可怕问题的一种可能:

  • 说您也许有一个显示某种时钟的容器视图。所以你有

    类时钟:UIViewController

您实际上在应用程序中的许多位置使用了它

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

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

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

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

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

自然地,您将出口添加到代码中。一切都应该工作。所有其他网点均正常运行。

您已确定链接了出口。

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

Xcode清楚地告诉您“您忘记连接电源了”。

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

崩溃实际上是由于您正在使用Clock!的另一个地方 >>> <<<<< / em>

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

崩溃实际上并非来自您的工作地点,而是来自另一个故事板,而该故事板上没有“ NewLabel”项目!

令人沮丧。

答案 16 :(得分:1)

还有一个......

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

答案 17 :(得分:1)

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

一旦我发现了这个并且文件名反映了类名,那就好了!

我希望能帮助别人。

答案 18 :(得分:1)

对我来说,这是崩溃,因为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)
}

答案 19 :(得分:1)

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

答案 20 :(得分:1)

其他情况:

直到视图控制器的视图实际被实例化之前,你的网点才会被设置,在你的情况下可能会在initWithNibName之后不久发生:bundle:-at这一点他们仍然是nil 。任何涉及这些插座的设置都应该在视图控制器的-viewDidLoad方法中进行。

答案 21 :(得分:1)

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

答案 22 :(得分:0)

复制一个类(链接到xib)后,我遇到了同样的问题,将它重用于另一个viewcontroller类(链接到storyboard)。 我忘了删除

override var nibName

override var nibBundle

方法

删除后,我的网点开始工作。

答案 23 :(得分:0)

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

答案 24 :(得分:0)

无意中我使用AVPlayerViewController代替UIViewController将视图控制器子类化。通过将其重播为UIViewController一些正常的东西。这应该有所帮助。

  

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

答案 25 :(得分:0)

检查您是否有丢失或断开连接的插座。

enter image description here

答案 26 :(得分:0)

我看到你使用ViewController !?在ViewController课程中,您必须使用-viewDidLoad -awakeFromNib-awakeFromNib用于UIView课程

答案 27 :(得分:0)

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

答案 28 :(得分:0)

就我而言,该应用突然突然崩溃。 对其进行调试发现,在nil时,所有出口仍为viewDidLoad()

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

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

let newVC = MYCustomViewController()

...由于某种原因,只要.xib命名为与视图控制器类相同(尽管不确定如何工作,就可以了。)。 not 调用{{ 1}}的参数为nil,或者像通常建议的那样在init(nibName:bundle:)上覆盖init()来这样做)。

所以我试图明确呼叫

self

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

  

***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无法在捆绑包中加载NIB:'NSBundle (已加载)',名称为“ MYCustomViewController”

然后然后,我看到了:

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


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

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

答案 29 :(得分:0)

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

答案 30 :(得分:0)

如果您有两个情节提要/ xib,对于继承层次结构中的每个“类级别”一个,则必须在每个中定义出口,并在需要对其进行操作的任何类中进行引用。就我而言,它是父类。