检索未包含在 CoreData 请求结果中的第二天

Posted

技术标签:

【中文标题】检索未包含在 CoreData 请求结果中的第二天【英文标题】:Retrieve the next day not included in a CoreData request result 【发布时间】:2014-06-02 10:05:09 【问题描述】:

我想通过从今天开始搜索并排除核心数据请求提供的日期来获得下一个可用日期。

我的初始化代码,以及在同一个类中实现的帮助方法

+ (NSDate *)getDateByAddingDays:(NSInteger)days toDate:(NSDate *)date 
    NSDate *newdate = [[NSDate alloc]init];
    if (days != 0) 
        NSDateComponents *components = [[NSDateComponents alloc] init];
        components.day = days;
        NSCalendar *calendar = [NSCalendar currentCalendar];
        newdate = [calendar dateByAddingComponents:components toDate:date
                                           options:0];
    
    return newdate;


+ (void)myTroublesomeMethod 

    // standard initialization of NSFetchRequest
    NSManagedObjectContext *context = [(id)[[UIApplication sharedApplication] delegate] managedObjectContext];

    NSDate *today = [NSDate date];

    NSFetchRequest *request3 = [[NSFetchRequest alloc] init];
    NSEntityDescription *chiusureDescription = [NSEntityDescription entityForName:@"Chiusure" inManagedObjectContext:context];
    NSError *error;
    [request3 setEntity:chiusureDescription];
    NSArray *arrayChiusure = [context executeFetchRequest:request3 error:&error];

    // I then extract the "data" attribute, that stores the date to be excluded

    NSMutableArray *giorniChiusura = [[NSMutableArray alloc]init];
        for (Chiusure *entity in arrayChiusure) 
            [giorniChiusura addObject:(NSDate*) entity.data];
        

    // and here is where the problem rises:

    NSInteger days = 0;
    NSDate *nextDate = [self getDateByAddingDays:days toDate:today];
    if ([arrayChiusure containsObject:nextDate]) 

        // HERE is the error, I suppose. nextDate is never contained in arrayChiusure, so the next while statement is an infinite loop.

        while ([arrayChiusure containsObject:nextDate]) 
            days += 1;
            nextDate = [self getDateByAddingDays:days toDate:today];
        

    // OMITTED: use of nextDate somewhere later in my code

我想到的替代方法

我知道我可以在while 中创建一个新的NSFetchRequest 循环以检查建议的 nextDate 是否包含在 Chiusure 实体数据集,但对我来说似乎有点矫枉过正。

附加信息

arrayChiusure 预计最多包含 10-20 个实体 我认为该错误与错误比较有关(即在 [arrayChiusure containsObject:nextDate] 中),但我不明白为什么

任何帮助表示赞赏:) 提前致谢

【问题讨论】:

1) entity.data 是什么类型,为什么必须将其转换NSDate *? - 2) 你知道NSDate 不仅代表“日”,而且代表一个绝对时间点(包括小时、分钟、秒和毫秒)。因此数组包含nextDate 的可能性非常低。 @MartinR 我将其转换为NSDate 只是为了让您知道这是一个NSDate 否则没有必要......简单的懒惰是为了不必解释我的全部核心数据实体定义 :#) 但是你是对的:我可以强制 nextDate 将小时、分钟、秒 = 设为 0 以匹配 entity.data,因为它是使用 RestKit 从 JSON“纯”日期数组填充的. 【参考方案1】:

正如评论中已经提到的,问题在于NSDate 不仅代表 天,而且时间可达毫秒。因此,您必须“标准化”日期 首先表示当前日期的午夜(或存储在 Core Data 对象中的任何内容)。

但是,有一个更简单的解决方案:您可以创建一个仅返回的 fetch 请求 商店中已经存在的最近日期(参见https://***.com/a/18395185/1187415 示例),然后添加一天。

例子:

NSArray *arrayChiusure = [context executeFetchRequest:request3 error:&error];

// Extract "data" attribute into new array:
NSArray *giorniChiusura = [arrayChiusure valueForKey:@"data"];

// nextDate = "today at midnight":
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
NSDate *nextDate;
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&nextDate interval:NULL forDate:today];

// Find next available day:
NSDateComponents *oneDay = [[NSDateComponents alloc]init];
oneDay.day = 1;
while ([giorniChiusura containsObject:nextDate]) 
    nextDate = [calendar dateByAddingComponents:oneDay toDate:nextDate options:0];

【讨论】:

更简单的解决方案是不正确的。如果 fetch 请求有两个或三个连续的日期怎么办?在第一个结果中添加一天仍然提供“禁止”日期 @furins:我的建议是获取 last 使用日期。 - 但可能是我误解了你的问题或简化了很多。如果您想找到今天之后的第一个未使用的日期,则必须规范化日期。您可以通过仅获取今天之后的对象并根据日期按升序对其进行排序来改进该方法。 我相信误解在于“使用”一词。我不会用“使用过的”日期填充核心数据,而是用未来 1-2​​ 年的国定假日来填充核心数据。因此,如果我获取 last 日期,我可能会在很远的将来得到一些东西,这是不可接受的,并且在 first 结果中增加 1 天。但是,由于您的帮助,我达到了可以接受的解决方案。由于我完全欠你我的答案,如果你愿意,你可以将它附加到你的答案中,我会删除我的。 @furins:好的,我想我现在明白了。我提出了另一个简化建议,但完全取决于您接受哪个答案。 非常感谢马丁。您的回答为我提供了想法、解决方案并教会了我很多东西。现在我必须与时区和夏令时作斗争,但这可能是另一个问题:)

以上是关于检索未包含在 CoreData 请求结果中的第二天的主要内容,如果未能解决你的问题,请参考以下文章

如何在 segue 中从 CoreData 获取结果

读取 CoreData 时出现罕见错误:CoreData 结果中的 data:<fault>

如何在Vue中的非父子组件之间共享数据

如何在Vue中的非父子组件之间共享数据

如何在Vue中的非父子组件之间共享数据

NSFetchRequest 检索 CoreData 实体中每个科目的每个学生的最高考试分数