【问题标题】:Why cant I unwrap this optional value using Swift?为什么我不能使用 Swift 解开这个可选值?
【发布时间】:2018-06-26 17:26:28
【问题描述】:

我正在尝试获取第一条记录的值,即“2018-05-04 09:00:00 +0000”。当我打印出 `firstRecord' 时,我会在终端中得到一个可选值:

可选(2018-05-04 09:00:00 +0000)。

然后我试着像这样打开它:

if dailyArray.count == 0 {
    print("no record was found")
}else{
    guard let firstRecord : String = dailyArray[0]["startTime"] as! String else {return}
    let firstRecordArray = firstRecord.components(separatedBy: " ")
    print("data exist \(firstRecordArray[0])")
}

现在 Xcode 给我一个错误,说你正在尝试解开一个非可选值。

知道我在哪里犯错了吗?

【问题讨论】:

  • dailyArray 是什么类型?确切的错误信息是什么? – 会不会是字符串“optional(...)”存储在字典中,即创建字典时已经出现问题?
  • optional(..) 带有小写“o”?你是如何创建那个字典/数组的?你能打印firstRecord.utf16.count吗?
  • as! 确实强制展开,所以它不是可选的。使用as?
  • 该输出表明您实际上有一个 Date 值,而不是一个 String 值。
  • @rmaddy 它可能是DateString,但如果它是Date 对象,它会因强制施放而崩溃。因此,正如所建议的那样,它的创建可能是错误的,并且应该在那里完成解包。即使小写的“o”看起来很奇怪。

标签: swift optional forced-unwrapping


【解决方案1】:

这样做

guard !dailyArray.isEmpty, let firstRecord = dailyArray[0]["startTime"] as? String else { return }
let firstRecordArray = firstRecord.components(separatedBy: " ")
print("data exist \(firstRecordArray[0])")

在你的代码中,你强制类型转换,为什么

["startTime"] as! String 

这意味着该值是 Strictly 字符串,而 ? 表示它可以是字符串

【讨论】:

  • 我也试过这个。它消除了错误但不产生任何输出:|
  • 您确定 dailyArray[0]["startTime"] 不是 nil 并且它实际上是 String 类型(而不是 Date)吗?如果你需要调试,你应该把guard语句分解成一系列的guard语句来找出哪个是失败的。能够链接保护语句很棒,但它使调试变得更加困难。
  • 我已经根据问题给出了解决方案,他需要和期待那里的字符串,否则他可以玩不同的类型
  • 而不是一系列的守卫只是简单的断点在调试中起作用,为什么有人想要他的代码可以单行到多行
  • @Danial Kosarifar: 只需在保护语句之前打印 array/ 的打印值或使用断点检查该值是否为字符串,同时您会看到数组是否为空
【解决方案2】:

如果你打算使用可选链,那么你也可以使用.first(在空数组上返回一个可选的nil)而不是[0](返回值,在空数组上崩溃):

guard !dailyArray.isEmpty else {
    print("no record was found")
    return
}
guard let firstRecord = dailyArray.first?["startTime"] as? String else {
    return
}
let firstRecordArray = firstRecord.components(separatedBy: " ")
print("data exist \(firstRecordArray[0])")

【讨论】:

  • @LeoDabus 没有坏处,它可以防止在前面的代码部分中进行重构。
【解决方案3】:

您可以使用可选链接和 if let 语法来解包变量并使代码更加简洁明了:

// dailyArray should be declared as or typecast to [[String : String]]

guard !dailyArray.isEmpty else {
    print("no record was found")
    exit(1) // or return if in func
}

if let firstRecord = dailyArray.first?["startTime"]?.components(separatedBy: " ") {
    print("data exists: \(firstRecord.first)")
}
else {
    print("no start time date was found")
}

【讨论】:

  • 而不是dailyArray.count > 0,通常最好这样做:!dailyArray.isEmpty。此外,不要直接下标 ([0]),而是使用 dailyArray.first?["startTime"]?.co...,因为您可以随意更改。
  • 根据评论更新。
猜你喜欢
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多