Swift:使用Calendar.component致App无报错冻结的解决方案
问题描述
背景
我有一个自定义Day结构体,内部使用Swift Date属性。我希望该结构体能够判断另一个给定的Day是否与自身为同一星期几。但每次执行相关代码时,我的App会冻结且无任何运行时错误。
代码
struct Day: Hashable { private let calendar: Calendar = .current let date: Date static func == (lhs: Day, rhs: Day) -> Bool { return Calendar.current.isDate(lhs.date, inSameDayAs: rhs.date) } func isSameDayOfTheWeek(as day: Day) -> Bool { // Replacing this Line to RETURN TRUE prevents the Crash. return calendar.component(.weekday, from: self.date) == calendar.component(.weekday, from: day.date) } } enum Time: Int16, Comparable, Identifiable, CaseIterable { case morning, noon, evening, night var id: Int16 { self.rawValue } var name: String { ... } } struct ToDo: Hashable, Identifiable { let id: UUID = UUID() let block: Block // NSManagedObject let day: Day let time: Time } struct ToDoView: View { @FetchRequest(sortDescriptors: [SortDescriptor(\.creationTS)]) private var blocks: FetchedResults<Block> var body: some View { ForEach(toDos) { toDo in Text(toDo.name) } } private var toDos: [ToDo] { var toDos: [ToDo] = [] for block in blocks { let startDay: Day = block.safeStartDay var day: Day = .today while day >= startDay { // Removing this Line prevents the Crash. guard startDay.isSameDayOfTheWeek(as: day) else { continue } for time in Time.allCases { toDos.append(ToDo(block: block, day: day, time: time)) } day = day - 1 } } return toDos } }
问题
如何解决该冻结问题,同时仍能判断另一个给定的Day是否与当前Day结构体实例为同一星期几?
解决方案
问题根源
App冻结是因为无限循环:在while day >= startDay循环中,当startDay.isSameDayOfTheWeek(as: day)条件不成立时,continue会跳过后续的day = day - 1代码,导致day的值始终不变,循环条件永远满足,无法退出。
修复步骤
1. 调整循环逻辑,避免无限循环
修改toDos计算属性的循环部分,确保无论是否匹配星期几的条件,都执行日期递减操作:
private var toDos: [ToDo] { var toDos: [ToDo] = [] for block in blocks { let startDay: Day = block.safeStartDay var day: Day = .today while day >= startDay { if startDay.isSameDayOfTheWeek(as: day) { for time in Time.allCases { toDos.append(ToDo(block: block, day: day, time: time)) } } // 无论条件是否满足,都必须递减日期,确保循环能正常退出 day = day - 1 } } return toDos }
2. 完善Day结构体的必要实现
确保Day结构体正确实现Comparable协议和减法操作符,保证day >= startDay和day = day -1的行为符合预期:
extension Day: Comparable { static func < (lhs: Day, rhs: Day) -> Bool { return lhs.date < rhs.date } static func - (lhs: Day, days: Int) -> Day { guard let newDate = lhs.calendar.date(byAdding: .day, value: -days, to: lhs.date) else { return lhs // 处理日期计算失败的边界情况 } return Day(date: newDate) } // 支持`day - 1`的简洁语法 static func - (lhs: Day, rhs: Int) -> Day { return lhs - rhs } } // 补充.today静态属性的实现(如果未定义) extension Day { static var today: Day { Day(date: Date()) } }
内容的提问来源于stack exchange,提问作者christophriepe
相关产品推荐
相关产品推荐

