【问题标题】:Swift unwrapped values still show as OptionalSwift 展开的值仍然显示为可选
【发布时间】:2017-03-18 04:54:40
【问题描述】:

我很难在没有Optional(...) 的情况下显示名称值。我以为我正在解开它们,但我无法摆脱可选的。我在 StackOverflow 上找到了一个解决方案,但在那种情况下,涉及到一个 as?,而这里不是这种情况。有问题的代码如下。有什么办法可以解开这些吗?我假设我遗漏了一些明显的东西。谢谢。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ClientCell

    cell.setBackground()

    let clientKey = clientSectionTitles[(indexPath as NSIndexPath).section]
    if let clientValues = clientDict[clientKey] {
        if self.sortBy == "First" {
            cell.clientName.text = clientValues[(indexPath as NSIndexPath).row].firstName! + " " + clientValues[(indexPath as NSIndexPath).row].lastName!
        } else {
            cell.clientName.text = clientValues[(indexPath as NSIndexPath).row].lastName! + ", " + clientValues[(indexPath as NSIndexPath).row].firstName!
        }
    }

    return cell
}

*编辑: 这是构建字典的代码:

func createClientDict() {
    var clientName: String?
    clientDict          = [String: [Client]]()
    clientSectionTitles = [String]()

    if self.sortBy == "First" {
        apiResults.sort (by: { $0.firstName < $1.firstName })
    } else {
        apiResults.sort (by: { $0.lastName < $1.lastName })
    }

    for c in apiResults {
        if self.sortBy == "First" {
            clientName = "\(c.firstName!) \(c.lastName!)"
        } else {
            clientName = "\(c.lastName!), \(c.firstName!)"
        }

        // Get the first letter of the name and build the dictionary
        let clientKey = clientName!.substring(to: clientName!.characters.index(clientName!.startIndex, offsetBy: 1))
        if var clientValues = clientDict[clientKey] {
            clientValues.append(c)
            clientDict[clientKey] = clientValues
        } else {
            clientDict[clientKey] = [c]
        }
    }

    // Get the section titles from the dictionary's keys and sort them in ascending order
    clientSectionTitles = [String](clientDict.keys)
    clientSectionTitles = clientSectionTitles.sorted { $0 < $1 }
}

*编辑:我还应该提到,这只发生在 Swift 3 中。它在 Swift 2.2 中运行良好。

【问题讨论】:

  • 与您的问题无关,但您为什么不必要地将indexPath 转换为NSIndexPath
  • 因为如果我不这样做,我会收到错误 Ambiguous use of 'row'。我想要一个更好的解决方案。这在迁移到 Swift 3 后开始发生。
  • 你使用的是什么版本的 Xcode?​​span>
  • @Sam_M,我使用的是 8.2.1
  • 使用任何第三方库?

标签: ios swift optional forced-unwrapping


【解决方案1】:

以下内容来自 Swift Programming Language Collection Types 文档:

您还可以使用下标语法从 特定键的字典。因为可以请求一个 不存在值的键,字典的下标返回 字典值类型的可选值。如果字典 包含请求键的值,下标返回一个 包含该键的现有值的可选值。除此以外, 下标返回 nil:

所以clientValues[(indexPath as NSIndexPath).row] 返回一个可选值

试试

cell.clientName.text = (clientValues[(indexPath as NSIndexPath).row].firstName!)!

*edited - 实际上最好使用可选绑定:

if let fname = clientValues[(indexPath as NSIndexPath).row].firstName! {
   cell.clientName.text = fname }

【讨论】:

  • 我收到错误 Cannot use optional chaining on non-optional value of type 'Client'? 在那里。如果我取出?,它会编译,但随后将值显示为可选。
  • 不走运。我尝试了以下方法,但仍然得到了一个可选值。这怎么可能? let fname: String! fname = clientValues[(indexPath as NSIndexPath).row].firstName! print(fname!) cell.clientName.text = fname!
  • 控制台显示为Optional("Ed")
  • 某处某事被定义为可选项?然后尝试强制解开它两次!这行得通吗...找到一种方法来打印名称。然后找出问题所在....
  • 事实证明,令人尴尬的是,问题不在于检索值,而在于保存。它已将Optional(\"Ed\")" 保存到数据库中,并且正在检索保存的内容。我将删除此问题,因为它对任何人都没有任何帮助。
【解决方案2】:

我认为这个问题与具有可选值的 clientKey 变量有关。在使用它之前尝试打开它,如下所示:

if let clientKey = clientSectionTitles[(indexPath as NSIndexPath).section] {
    if let clientValues = clientDict[clientKey] {
        if self.sortBy == "First" {
            cell.clientName.text = clientValues[(indexPath as NSIndexPath).row].firstName! + " " + clientValues[(indexPath as NSIndexPath).row].lastName!
        } else {
            cell.clientName.text = clientValues[(indexPath as NSIndexPath).row].lastName! + ", " + clientValues[(indexPath as NSIndexPath).row].firstName!
        }
    }
}

=== 编辑:===

 let clientKey = clientSectionTitles[(indexPath as NSIndexPath).section] 
        if let clientValues = clientDict[clientKey] {
            if self.sortBy == "First" {
                cell.clientName.text = clientValues[(indexPath as NSIndexPath).row].firstName! + " " + clientValues[(indexPath as NSIndexPath).row].lastName!
            } else {
                cell.clientName.text = clientValues[(indexPath as NSIndexPath).row].lastName! + ", " + clientValues[(indexPath as NSIndexPath).row].firstName!
            }
        }

【讨论】:

  • 我在第一行得到Initializer for conditional binding must have Optional type, not 'String'
  • @kuzdu,我试过了,它仍然显示为可选。
  • @Lastmboy,您在哪一行收到错误“条件绑定的初始化程序必须具有可选类型,而不是'字符串'”?请告诉我,
  • 编辑了答案,让我知道现在发生了什么。
  • @Tushar,正如我在下面提到的,问题显然出在保存到数据库中。它将Optional(\"Ed\") 保存为数据,并且只是在检索它。价值本身并不是真正的选择。很尴尬。感谢你的帮助。我将删除此问题,因为它可能对任何人都没有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
相关资源
最近更新 更多