Swift计算App内每日锻炼评分平均值返回NaN问题求助
解决锻炼项目平均评分返回NaN的问题
嘿,我来帮你排查这个平均评分返回NaN的问题~首先,NaN出现的核心原因基本是0除以0,或者计算过程中混入了无效数值,我们结合你的代码一步步分析:
最可能的问题:workouts为空却没被拦截
你的guard let workouts = workouts?.allObjects as? [Workout] else { return 0 }只处理了workouts为nil的情况,但如果workouts?.allObjects返回的是空数组,这个guard会直接通过!这时候workouts.count是0,total是0,0除以0自然就得到NaN了。
为什么会出现这种情况?大概率是当前的Appointment对象并没有关联到任何Workout记录——哪怕数据库里有Workout数据,但它们不属于这个Appointment;或者是Core Data的关联关系配置出了问题,导致关联数据没正确加载。
另一个潜在问题:review字段存在无效值
如果Workout的review是可选类型(比如Double?),或者数据库里某些review存储了NaN值,也可能导致计算异常。不过你没崩溃反而得到NaN,那更倾向于第一种空数组的情况。
修复后的代码
我给你调整了代码,既处理了空数组的情况,也过滤掉无效的评分数据:
适用于review为可选类型的版本
extension Appointment { func averageReview() -> Double { // 先确保能拿到workouts,且数组不为空 guard let workouts = workouts?.allObjects as? [Workout], !workouts.isEmpty else { return 0 // 这里可以根据需求改默认值,比如返回0或者提示无数据 } // 过滤掉评分为nil的无效数据 let validWorkouts = workouts.filter { $0.review != nil } guard !validWorkouts.isEmpty else { return 0 } // 计算总分和平均分 let total = validWorkouts.reduce(0.0) { $0 + $1.review! } let average = total / Double(validWorkouts.count) return average } }
适用于review为非可选Double类型的版本
extension Appointment { func averageReview() -> Double { guard let workouts = workouts?.allObjects as? [Workout], !workouts.isEmpty else { return 0 } // 过滤掉可能的NaN评分 let validReviews = workouts.map { $0.review }.filter { !$0.isNaN } guard !validReviews.isEmpty else { return 0 } let total = validReviews.reduce(0.0, +) let average = total / Double(validReviews.count) return average } }
额外排查小技巧
你可以在函数里加两行打印,快速定位问题:
print("当前关联的Workout数量:\(workouts.count)") print("总分:\(total)")
运行后看控制台输出,就能确认是不是count为0导致的0/0问题。另外也可以打印workouts的内容,确认这些Workout是不是真的有有效评分数据。
内容的提问来源于stack exchange,提问作者Matt Brown
相关产品推荐
相关产品推荐

