【问题标题】:How can I dynamically work with FetchRequest data in SwiftUI view如何在 SwiftUI 视图中动态处理 FetchRequest 数据
【发布时间】:2020-09-18 06:11:10
【问题描述】:

我正在尝试使用 SwiftUI 创建一个卡路里计数器视图,其中锻炼数据是从核心数据中获取的,除了写出所有数据之外,我还想获得今天燃烧的卡路里总数。我正在考虑查看获取的数据,检查其createdAt 属性是否等于当前Date(),如果是,则将其加起来为self.totalCaloriesBurntToday 的总和。

我收到一个错误,指出这种类型的 ForEach 不符合某些协议:

类型'()'不能符合'View';只有结构/枚举/类类型可以符合协议

这是我的代码:

import SwiftUI

struct ProgressBar: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(
        entity: WorkoutInputData.entity(),
        sortDescriptors: []
    ) var workoutData: FetchedResults<WorkoutInputData>

    @State private var totalCaloriesBurntToday : Int


    var body: some View {
        ForEach(workoutData) { singleWorkout in
            if singleWorkout.createdAt == Date(){
                self.totalCaloriesBurntToday += Int(singleWorkout.caloriesBurnt)!
            }
        }
        return Text("\(self.totalCaloriesBurntToday)")
    }
}

我想稍后输出总和并希望它动态改变。每次添加或删除某些数据对象时,总和都会自动调整。

我尝试使用 UserDefaults 来解决这个问题,以节省卡路里,但存在的问题是 UserDefaults 中的数据更改不会自动推动视图中的更改,因此它不是动态的。

【问题讨论】:

  • 我不认为 ForEach 是正确的方法,你应该使用像 reduce 这样的高阶函数。另请注意,Datr() 不仅会给出今天的日期,还会给出当前时间,因此 == 比较会产生很多结果

标签: swift foreach swiftui nsfetchrequest


【解决方案1】:

您使用的 SwiftUI 的 ForEach 的返回类型为 Content,这意味着对于循环中的每个项目,它必须返回一些 View。它与简单的foreach 循环不同。

您可以使用reduce 计算totalCaloriesBurntfilter 以仅选择今天的锻炼。

为了比较日期,最好使用Calendar.compare

Calendar.current.compare(singleWorkout.createdAt, to: Date(), toGranularity: .day) == .orderedSame

总结您的代码可能如下所示:

workoutData
  .filter { Calendar.current.compare($0.createdAt, to: Date(), toGranularity: .day) == .orderedSame }
  .reduce(0) { $0 + Int($1.caloriesBurnt)! }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-31
    • 2020-04-17
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    相关资源
    最近更新 更多