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 中连接了插座。
想法:
- 有没有可能是因为我使用的是子类的子类,导致初始化出现问题?我没有覆盖任何初始化器
awakeFromNib:
由于某种原因没有被调用
- 也许它没有连接到子视图上的子视图
我尝试过的东西:
- 完全匹配
@IBOutlet
和故事板项目类型(而不是 UIView
)
- 正在删除 属性 和插座并重新添加它们
图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 内容。在 运行 时间所有引用都是零。所以我清除了我的派生数据文件夹,然后这些连接再次工作。
你试过了吗运行产品>清洁。为我解决了一个非常相似的问题。
- select
.h
和 .m
查看控制器文件
- 删除那些文件的引用
- 将文件重新添加到您的项目树
- 打开故事板,最终重新构建项目
我最近遇到了这个问题!这是我的想法。
问题不在于您的情节提要或任何 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 似乎构建良好,并覆盖了 viewDidLoad
、viewWillAppear
等函数。正常工作。但是 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 的工作解决方案
- 创建 class 自定义视图控制器:UIViewController
- 创建视图CustomViewControllerView.xib
- 在 Interface Builder CustomViewControllerView.xib 中 select 占位符 -> 文件所有者
- 在 "Attributes inspector" 中将 Class 设置为 CustomViewController
- 在 "Connections inspector" 中将 "view" 连接到 xib 的顶层视图(确保顶层视图的 Class 没有指向 CustomViewController)
- 在"Connections inspector"连接其他插座(如果needed/exist)
- 在父视图中创建 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.
使用 Swift 1.1 和 Xcode 6.2。
我有一个包含单个自定义 UIViewController
子类的 UIStoryboard。在它上面,我有一个 @IBOutlet
类型的 UIView
连接,从该控制器到故事板上的 UIView
子类 。对于该视图的子视图,我也有类似的出口。见图A.
但在 运行 时,这些属性为零(图 B)。尽管我已经确定我已经在 Interface Builder 中连接了插座。
想法:
- 有没有可能是因为我使用的是子类的子类,导致初始化出现问题?我没有覆盖任何初始化器
awakeFromNib:
由于某种原因没有被调用- 也许它没有连接到子视图上的子视图
我尝试过的东西:
- 完全匹配
@IBOutlet
和故事板项目类型(而不是UIView
) - 正在删除 属性 和插座并重新添加它们
图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 内容。在 运行 时间所有引用都是零。所以我清除了我的派生数据文件夹,然后这些连接再次工作。
你试过了吗运行产品>清洁。为我解决了一个非常相似的问题。
- select
.h
和.m
查看控制器文件 - 删除那些文件的引用
- 将文件重新添加到您的项目树
- 打开故事板,最终重新构建项目
我最近遇到了这个问题!这是我的想法。 问题不在于您的情节提要或任何 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 似乎构建良好,并覆盖了 viewDidLoad
、viewWillAppear
等函数。正常工作。但是 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 的工作解决方案
- 创建 class 自定义视图控制器:UIViewController
- 创建视图CustomViewControllerView.xib
- 在 Interface Builder CustomViewControllerView.xib 中 select 占位符 -> 文件所有者
- 在 "Attributes inspector" 中将 Class 设置为 CustomViewController
- 在 "Connections inspector" 中将 "view" 连接到 xib 的顶层视图(确保顶层视图的 Class 没有指向 CustomViewController)
- 在"Connections inspector"连接其他插座(如果needed/exist)
- 在父视图中创建 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.