Swift 如何在过滤数组时安全地解包可选的 属性?

Swift How could I safely unwrap an optional property when filtering an array?

我正在尝试使用对象的 class 的可选 属性 来过滤对象数组,所以我想知道安全解包此 属性 的最佳方法是什么而不用提供默认值。 属性 是 Date 类型,因此提供替代值感觉就像是 hack,但我不确定如何做得更好。我知道如何使用 guard 安全地解包常规可选,但我不确定在过滤数组时如何使用它。我的代码是这样的:

let completedGoalsThisWeek = goals.filter { [=12=].returnWeek(date: [=12=].dateAchieved) == deviceWeek }.count

问题中的 属性 是 dateAchieved,在很多情况下它会是 nil。

谢谢。

此处出错

[=10=].returnWeek(date: [=10=].dateAchieved) == deviceWeek 

可以通过使参数 date 成为可选值来解决,这将使 return 也成为可选值,但它会通过,因为您可以将可选值与非值

进行比较

returnWeek 会像

func returnWeek(date:Date?) -> TypeOFWeek? {
  guard let res = date else { return nil }
  // here return valid result 
}

let completedGoalsThisWeek = goals.filter { [=12=].dateAchieved != nil ?  ( [=12=].returnWeek(date: [=12=].dateAchieved!) == deviceWeek ) : false }.count

或者更好的模型

class Model { 
  var toWeek: TypeOfWeek? {
    // do where what in function which uses dateAchieved
  }
}

let completedGoalsThisWeek = goals.filter { [=13=].toWeek  == deviceWeek }.count

没什么特别的。就像在任何其他情况下一样打开可选的:

let completedGoalsThisWeek = goals
    .lazy
    .filter { goal -> Bool in
        guard let dateAchieved = goal.dateAchieved else { return false }
        let isCurrentWeek = goal.returnWeek(date: dateAchieved) == deviceWeek
        return isCurrentWeek
    }.count

可以 使用 Optional.map 来缩短它,但我建议不要这样做,它太神秘了:

let completedGoalsThisWeek = goals
    .lazy
    .filter { goal
        goal.dateAchieved.map { goal.returnWeek(date: [=11=]) == deviceWeek } ?? false
    }.count

在任何一种情况下,我建议您使用 .lazy.filter,以防止中间分配保存元素数组,如果您最终只打算对它们进行计数并立即丢弃它们的话。