1

这是我在 stackoverflow 上的第一个问题。这个社区对我很有帮助,它为我的 iPhone 应用程序开发提供了很多解决方案。但是,我这周遇到了一个问题,花了两天时间没有任何进展。我在这里发布问题,希望能在你们的帮助下得到解决。

我正在使用 coredata 并且有两个表,Prayers 和 Schedules,具有多对多的关系。我想得到一份今天安排的祈祷清单。这是我的代码:

    NSPredicate *predicate;
    unsigned units = NSDayCalendarUnit | NSMonthCalendarUnit | NSWeekCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;

    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [gregorian setTimeZone:[NSTimeZone localTimeZone]]; 
    [gregorian setFirstWeekday:1];
    NSDateComponents* comps = [gregorian components:units fromDate:[NSDate date]]; // Get necessary date components
    [comps setHour:0];
    [comps setMinute:0];
    [comps setSecond:1];

    //get beginning of today
    NSDate *startOfToday = [gregorian dateFromComponents:comps];
    //get the beginning of tomorrow
    [comps setDay:[comps day] + 1];
    NSDate *endOfDay = [gregorian dateFromComponents:comps];

    NSLog(@"%@ %@", startOfToday,endOfDay);

    predicate = [NSPredicate predicateWithFormat:@"ANY (schedules.nextEventDateTime >= %@ AND schedules.nextEventDateTime < %@) AND prayerType == 0 AND finished == YES AND answered == NO", startOfToday, endOfDay];

    [request setPredicate:predicate];
        NSError *error = nil;
    NSArray *fetchResults = [context executeFetchRequest:request error:&error];

在我升级到 xcode 4.5.2 和 ARC 之前,这段代码可以正常工作。在我使用 xcode 4.5.2 将应用程序转换为 ARC 之后。运行应用程序时,我在以下行出现错误(崩溃)(其他一切似乎都很好):

    predicate = [NSPredicate predicateWithFormat:@"ANY (schedules.nextEventDateTime >= %@ AND schedules.nextEventDateTime < %@) AND prayerType == 0 AND finished == YES AND answered == NO", startOfToday, endOfDay];

控制台输出和错误是:

     2013-03-15 23:41:36.763 WePrayers[12121:c07] 2013-03-15 04:00:01 +0000 2013-03-16 04:00:01 +0000

     2013-03-15 23:41:37.837 WePrayers[12121:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "ANY (schedules.nextEventDateTime >= %@ AND schedules.nextEventDateTime < %@) AND prayerType == 0 AND finished == YES AND answered == NO"'
     *** First throw call stack:
     (0x29f2012 0x20ebe7e 0x1abc25 0x1aba43 0x1ab9f7 0x19ce5 0x186fb 0x61e8d5 0x61eb3d 0x190e83 0x29b1376 0x29b0e06 0x2998a82 0x2997f44 0x2997e1b 0x2f207e3 0x2f20668 0x56f65c 0x2ecd 0x2e05)
     libc++abi.dylib: terminate called throwing an exception

我尝试将行更改为以下内容,并且没有任何问题:

    predicate = [NSPredicate predicateWithFormat:@"ANY schedules.nextEventDateTime >= %@ AND prayerType == 0 AND finished == YES AND answered == NO", startOfToday];

但是,我需要比较 schedules.nextEventDateTime >= startOfToday 和 < endOfDay 以获取仅适用于今天的时间表。

如果我将行更改为以下内容(删除括号)

    predicate = [NSPredicate predicateWithFormat:@"ANY schedules.nextEventDateTime >= %@ AND schedules.nextEventDateTime < %@ AND prayerType == 0 AND finished == YES AND answered == NO", startOfToday, endOfDay];

它将运行通过此行但在行上失败: NSArray *fetchResults = [context executeFetchRequest:request error:&error];

错误是:*由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“此处不允许多对多键”

谁能知道我的代码有什么问题?任何建议和意见都非常感谢。

谢谢,乔

4

1 回答 1

0

我认为在您的情况下SUBQUERY可能会对您有所帮助。

predicate = [NSPredicate predicateWithFormat:@"prayerType == 0 AND finished == YES AND answered == NO AND SUBQUERY(schedules, $sub, $sub.nextEventDateTime >= %@ AND $sub.nextEventDateTime <  %@).@count > 0", startOfToday, endOfDay];

并注意表达顺序。一般来说,连接(跨关系的查询)也是昂贵的操作,如果可以的话,你应该避免它们。除非第一个测试成功,否则避免进行连接。

于 2013-03-16T10:12:53.240 回答