如何在SwiftUI中从NSManagedObject删除重复的日期(无时间)

我有一个此类,它是从Xcode / Core Data自动生成的,称为activity的Core Data实体。

@objc(activity)
public class activity: NSManagedObject {

}

extension activity {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<activity> {
        return NSFetchRequest<activity>(entityName: "activity")
    }

    @NSManaged public var name: String
    @NSManaged public var date: Date

}

我如何才能获得具有不同日期(没有时间)的结果,而不仅仅是一个视图没有重复的日期,而是另一视图的所有日期(未过滤)?

我不确定,是否需要修改我的活动类并使用自定义函数对其进行扩展,或者是否可以对@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \activity.name,ascending: true)]) var activites: FetchedResults<activity>应用过滤器,或者是否需要直接处理请求的结果在List(activities,id: \.self)中。

我需要同时具有所有日期和已过滤日期的灵活性。过滤的活动不需要名称,并且不能唯一。我只想要带有日期(无时间)字符串的列表。未过滤的列表需要名称和日期。

例如:

  • 2020-06-22
  • 2020-05-20
  • 2020-05-20
  • 2020-05-20
  • 2020-03-02

应过滤为

  • 2020-06-22
  • 2020-05-20
  • 2020-03-02
iCMS 回答:如何在SwiftUI中从NSManagedObject删除重复的日期(无时间)

您描述的问题并非真的那么简单。

您使用的Date是一个从特定时间点开始以秒为单位定义的时间戳。它与任何日历都不相关。 但是,您显示的字符串是基于日历的,并且是对给定时间戳的解释。

因此,当使用日历(包括时区)时,两个日期不同的用户对单个日期的解释可能会有所不同,主要取决于时区。

我认为该数据库将Date对象存储为64位浮点值。因此,要获取过滤后的日期,您基本上是在获取所有唯一值,这些值首先通过一些荒谬的“日历”算法进行了四舍五入。祝你好运。

最简单的方法是在内存中执行此操作。您可以提取所有条目,然后使用字典对项目进行分组:

func sortEntriesByDays(_ activities: [Activity]) -> [Date: [Activity]] {
    let calendar = Calendar.autoupdatingCurrent
    
    var sortedItems: [Date: [Activity]] = [Date: [Activity]]()
    
    activities.forEach { activity in
        let dayStartDate = calendar.date(from: calendar.dateComponents([.year,.month,.day],from: activity.date))!
        
        var activities: [Activity] = sortedItems[dayStartDate] ?? [Activity]()
        activities.append(activity)
        
        sortedItems[dayStartDate] = activities
    }
    
    return sortedItems
}

您只需在其上调用.keys,即可从此方法的结果中获取所有唯一日期。

这可能是最简单,最安全的解决方案。唯一的问题是,当数据库中有很多条目时,您可能不希望仅显示一些条目就加载所有(或很多)条目。在这种情况下,获取结果控制器非常有用,但是要使用它,您可能需要更改数据库。

一种方法是将2个日期存储在Activity中。一个是您已经存储的实际日期,另一个是它所属日期的开始。您可以简单地创建一个setDate方法来设置两个日期。第二个仅使用代码:calendar.date(from: calendar.dateComponents([.year,from: activity.date))!

一种非常相似的方法是,按照您所描述的,仅使用格式yyyy-MM-dd添加一个字符串。与以前的想法相去不远。

然后另一种方法是创建另一个实体Day,该实体拥有与您的活动对象多对一的关系。因此,每项活动都应精确地参考一天。因此,当将一项活动插入数据库时​​,它应尝试找到相应的日对象并与其连接。如果没有这样的Day对象,则需要创建一个。修改对象后,需要重新检查它是否属于同一天。从Day对象中删除活动后,您还需要检查是否还有其他活动,如果没有活动,则从数据库中删除Day对象。

但是,当用户更改时区(可能是旅行时)时,无论您使用这三个选项中的哪一个,您都可能会遇到问题。发生这种情况时,代码calendar.date(from: calendar.dateComponents([.year,from: activity.date))!将产生不同的结果,并且活动现在可能属于另一个Day对象。您可以检测到该更改并重组数据库...

本文链接:https://www.f2er.com/2022476.html

大家都在问