【问题标题】:Fatal error: unexpectedly found nil while unwrapping an Optional values [duplicate]致命错误:在展开可选值时意外发现 nil [重复]
【发布时间】:2014-08-29 21:06:10
【问题描述】:

我在 Swift 中使用了 UICollectionView,但是当我尝试更改单元格标签的文本时,我得到了。

    func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int
{
    return 5
}

func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell!
{
    var cell = collectionView.dequeueReusableCellWithReuseIdentifier("title", forIndexPath: indexPath) as TitleCollectionViewCell
    // Next line: fatal error: unexpectedly found nil while unwrapping an Optional value
    cell.labelTitle.text = "This is a title"
    return cell
}

有人知道吗?

【问题讨论】:

  • 检查cell.labelTitle 不是nil
  • ...而且cell 也不是nil
  • 看起来像重复的标记是错误的,因为这是在 2014 年 7 月 9 日首次提出的
  • 由于重复的问题也适用于这个问题,我建议不要关闭它。答案只会复制另一个主题。
  • 那些投票重新打开这个问题的人应该考虑这样一个事实,即“在展开可选值时意外发现快速致命错误”在 Google 上排名第一——我想这是大多数新的 Swift 开发人员在第一次滥用崩溃运算符! 或隐式展开的选项后会执行的查询。我们应该将这些人引导到有关此主题的规范问答,而不是让他们回答有关 UICollectionView 的特定问题。如果要重新打开此问题,则应更改标题以反映具体问题。

标签: ios swift uicollectionview


【解决方案1】:

您可以通过使用if let 语句安全地解开cell.labelTitle 来防止崩溃发生。

if let label = cell.labelTitle{
    label.text = "This is a title"
}

你仍然需要做一些调试来看看为什么你在那里得到一个 nil 值。

【讨论】:

  • 这对我来说很奇怪,因为如果您获取属性而不是设置它,这不只是一个问题吗?
  • 其实我的问题不同,tableView.tableFooterView = UIView() 是我的代码中断的地方
  • 这对于任何生产代码来说都是非常重要的良好实践。
【解决方案2】:

几乎可以肯定,您的重用标识符 "title" 不正确。

dequeueReusableCellWithIdentifierUITableView.h方法签名我们可以看出,返回类型是一个Implicitly Unwrapped Optional

func dequeueReusableCellWithIdentifier(identifier: String!) -> AnyObject! // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.

AnyObject后面的感叹号决定:

    AnyObject!

那么,首先要考虑的是,什么是“隐式展开的可选”?

The Swift Programming Language 告诉我们:

有时从程序的结构中可以清楚地看出,可选将 在第一次设置该值之后,总是有一个值。在这些情况下,它 对于消除检查和解包可选值的需要很有用 每次访问它,因为可以安全地假设它有一个 始终保持价值。

这些类型的可选项被定义为隐式展开 选项。您通过放置一个隐式展开的可选项 感叹号(字符串!)而不是问号(字符串?) 您要设为可选的类型。

所以,基本上,有些东西可能在某一时刻可能是 nil,但从某一时刻开始,它就再也不会是 nil 了。因此,我们将其作为展开后的值来省去一些麻烦。

在这种情况下,dequeueReusableCellWithIdentifier 返回这样的值是有意义的。提供的标识符必须已经用于注册单元以供重用。提供不正确的标识符,出队找不到它,并且运行时返回一个永远不会发生的 nil。这是一个致命错误,应用程序崩溃,控制台输出给出:

fatal error: unexpectedly found nil while unwrapping an Optional value

底线:检查您在 .storyboard、Xib 或代码中指定的单元重用标识符,并确保在出列时它是正确的。

【讨论】:

  • 这是正确答案,不是标记的那个。
  • 所以基本上一个隐式展开的 Optional 永远不应该返回 nil
  • @Ran 这就是确切的原因,我们也应该始终阅读其他答案。
【解决方案3】:

检查单元格是否正在self.collectionView.registerClass(cellClass: AnyClass?, forCellWithReuseIdentifier identifier: String) 注册。如果是这样,则删除该行代码。

有关更多信息,请参阅此答案: Why is UICollectionViewCell's outlet nil?

“如果您使用的是故事板,您不想调用它。它会覆盖您在故事板中的内容。”

【讨论】:

    【解决方案4】:

    我不知道是错误还是什么,但是当您使用自定义单元格时,您的标签和其他 UI 不会自动初始化。你应该在你的UICollectionViewController 课堂上试试这个。它对我有用。

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let nib = UINib(nibName: "<WhateverYourNibName>", bundle: nil)
        self.collectionView.registerNib(nib, forCellReuseIdentifier: "title")
    }
    

    【讨论】:

    • 你如何找到 >WhateverYourNibName> 是?
    • 应该是你自定义collectionView单元格的名字(.xib)
    【解决方案5】:

    替换此行 cell.labelTitle.text = "This is a title"
    cell.labelTitle?.text = "This is a title"

    【讨论】:

      【解决方案6】:

      我在尝试访问UILabel 时遇到了他的错误。我忘记在 Storyboard 中将 UILabel 连接到 IBOutlet,这导致应用程序因此错误而崩溃!!

      【讨论】:

        【解决方案7】:

        我也遇到了这个问题,问题出在视图控制器上。我不确定您的应用程序的结构如何,所以我将解释我发现的内容。我对 xcode 和编码很陌生,所以请耐心等待。

        我试图以编程方式更改 UILabel 上的文本。使用“self.mylabel.text”工作得很好,直到我在同一个类下添加了另一个视图控制器,它也不包含该标签。那是我收到您所看到的错误的时候。当我添加相同的 UILabel 并将其连接到那个额外的视图控制器时,错误就消失了。

        简而言之,似乎在 Swift 中,分配给同一个类的所有视图控制器都必须引用您在其中的代码,否则会出现错误。如果您有两个具有不同代码的不同视图控制器,请将它们分配给不同的类。这对我有用,并希望适用于你正在做的事情。

        【讨论】:

          【解决方案8】:

          致命错误:在展开可选值时意外发现 nil

          1. 检查 IBOutlet 集合,因为这个错误可能会导致未连接的 uielement 对象使用。

          :) 希望对一些苦苦挣扎的人有所帮助。

          【讨论】:

            【解决方案9】:

            我自己四处寻找解决方案。只有我的问题与您在此处提到的 UITableViewCell 而不是 UICollectionView 有关。

            首先,我是 iOS 开发的新手。就像全新的一样,坐在这里试图通过我的第一个教程,所以不要相信我的话。 (除非它的工作;))

            我没有得到对 cell.detailTextLabel.text 的引用 - 在重新观看了我关注的教程视频后,看起来我没有错过任何内容。所以我输入了 UITableViewCell 的头文件并找到了这个。

            var detailTextLabel: UILabel! { get } // default is nil. label will be created if necessary (and the current style supports a detail label).

            所以我注意到它说(并且当前样式支持详细标签) - 好吧,自定义样式默认情况下没有详细标签。所以我只需要在故事板中切换单元格的样式,一切都很好。

            我猜你的标签应该一直在那里?

            因此,如果您遵循 connor 的建议,这基本上意味着,如果该标签可用,则使用它。如果您的样式设置正确并且重用标识符与情节提要中的一组匹配,则除非您使用多个自定义单元格,否则您不必进行此检查。

            【讨论】:

            • 我在PFQueryTableViewController 上遇到了这个问题。在阅读了这个答案之后,我有一个灯泡时刻,Parse 中的表可能是空的(即使它不是但可能第一次使用它默认返回 nil?)。但是我改变了我查询的列并且它有效。
            【解决方案10】:

            Nil Coalescing Operator 也可以使用。

            rowName = rowName != nil ?rowName!.stringFromCamelCase():""
            

            【讨论】:

              【解决方案11】:

              我在 Xcode 7.3 上遇到了同样的问题。我的解决方案是确保我的单元格具有正确的重用标识符。在表格视图部分下,将表格视图单元格设置为您在程序中使用的相应标识符名称,确保它们匹配

              【讨论】:

                【解决方案12】:

                我遇到了同样的问题,原因是我试图加载一个名称错误的 UIImage。仔细检查.setImage(UIImage(named: "-name-" 调用并确保名称正确。

                【讨论】:

                  【解决方案13】:

                  这里的信息相同,但原因不同。我有一个UIBarButton 推动了一个转场。 segue 缺少标识符。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-01-26
                    • 2016-02-29
                    • 2020-09-19
                    相关资源
                    最近更新 更多