Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/96.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何计算CoreData对象的唯一日期?_Ios_Core Data_Count_Nsdate_Nsmanagedobject - Fatal编程技术网

Ios 如何计算CoreData对象的唯一日期?

Ios 如何计算CoreData对象的唯一日期?,ios,core-data,count,nsdate,nsmanagedobject,Ios,Core Data,Count,Nsdate,Nsmanagedobject,我需要一种正确的方法来计算具有NSDate类型属性的CoreData对象中有多少唯一的天数 例如,我有以下几点: <Object>.date = "2014-05-15 21:29:12 +0000"; <Object>.date = "2014-05-15 21:49:34 +0000"; <Object>.date = "2014-05-16 13:29:23 +0000"; <Object>.date = "2014-05-16 20:49:

我需要一种正确的方法来计算具有NSDate类型属性的CoreData对象中有多少唯一的天数

例如,我有以下几点:

<Object>.date = "2014-05-15 21:29:12 +0000";
<Object>.date = "2014-05-15 21:49:34 +0000";
<Object>.date = "2014-05-16 13:29:23 +0000";
<Object>.date = "2014-05-16 20:49:50 +0000";
<Object>.date = "2014-05-16 22:01:53 +0000";
<Object>.date = "2014-05-20 03:32:12 +0000";
<Object>.date = "2014-05-20 12:45:23 +0000";
<Object>.date = "2014-05-20 14:15:50 +0000";
<Object>.date = "2014-05-20 20:20:05 +0000";
.date=“2014-05-15 21:29:12+0000”;
.date=“2014-05-15 21:49:34+0000”;
.date=“2014-05-16 13:29:23+0000”;
.date=“2014-05-16 20:49:50+0000”;
.date=“2014-05-16 22:01:53+0000”;
.date=“2014-05-20 03:32:12+0000”;
.date=“2014-05-20 12:45:23+0000”;
.date=“2014-05-20 14:15:50+0000”;
.date=“2014-05-20:20:05+0000”;
在这种情况下,结果必须是3,因为有3个不同的日期,2014-05-15、2014-05-16和2014-05-20

有办法解决这个问题吗? 我尝试了NSPredicate,但没有成功


谢谢

那很容易。让我告诉你我要为它做什么

使用排序描述码对结果进行分组。此示例帮助您了解如何实现它

然后计算这些组

编辑:

NSDate+Utils.h

- (NSDate *) dateWithoutTime
NSDate+Utils.m

-(NSDate *) dateWithoutTime
{
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:self];
    return [calendar dateFromComponents:components];
}
一些文件

- (NSUInteger) someObjectsCount
{
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"SomeObject"];

    NSString *key = @"date.dateWithoutTime";

    fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:key
                                                                 ascending:YES]];

    NSManagedObjectContext *context;
    context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];

    NSFetchedResultsController *aFetchedResultsController;
    aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:context
                                                                      sectionNameKeyPath:key
                                                                               cacheName:nil];
    [aFetchedResultsController performFetch:nil];

    return [[aFetchedResultsController sections] count];
}

就这些

您应该有一个名为“daydate”的新属性,该属性是从当前日期和时间设置为午夜的日期

每次创建/修改其中一个对象时,操作如下:

NSDate *date = [NSDate date];

NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];
NSDateComponents *dateComps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
NSDate *daydate = [calendar dateFromComponents:dateComps];

myObject.date = date;
myObject.daydate = daydate;
然后,您可以操作取回(2个选项)

备选案文1:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"myObject" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];

NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"daydate"];
NSExpression *functionExpression = [NSExpression expressionForFunction:@"count:" arguments:@[keyPathExpression]];

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"count for this daydate:"];
[expressionDescription setExpression:functionExpression];
[expressionDescription setExpressionResultType:NSDoubleAttributeType];

NSAttributeDescription *attributeDesc = (entity.attributesByName)[@"daydate"];

[request setPropertiesToFetch:@[attributeDesc, expressionDescription]];
[request setPropertiesToGroupBy:@[attributeDesc]];
[request setResultType:NSDictionaryResultType];

NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error];
NSLog(@"array: %@", array);
NSLog(@"%lu", (unsigned long)array.count);
备选案文2:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"myObject" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
request.returnsDistinctResults = YES;
request.propertiesToFetch = @[@"daydate"];
request.resultType = NSDictionaryResultType;

NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error];
NSLog(@"array: %@", array);
NSLog(@"array count: %lu", (unsigned long)array.count);

我在我的一个应用程序中也遇到了同样的问题,我从来没有找到一个谓词可以帮我解决这个问题

我目前查看实体中的所有对象,计算每个日期的日期,然后返回一个唯一日期数组。我正在考虑为我的实体添加一个day属性,但尚未测试该概念

下面是我目前使用的代码。注:

  • 这两种方法都是名为
    Game
  • 我的模型中的实体称为
    Game
    ,我想转换为唯一天数的属性是
    startDateTime
  • 返回的数组包含按相反顺序排序的唯一日期(最新日期优先)
  • 如果您不关心实际的唯一天数,而只关心唯一天数的计数,那么只需更改代码即可返回天数计数(
    [uniqueDays count]
  • 我的代码:

    + (NSArray *)allGameStartDaysInManagedObjectContext:(NSManagedObjectContext *)moc {
        __block NSArray *gameDates;
    
        // mod cannot be nil
        NSParameterAssert(moc);
    
        [moc performBlockAndWait:^{
            NSError *error;
    
            NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Game"];
            NSArray *game = [moc executeFetchRequest:request error:&error];
    
            // Check for errors
            if (!game) {
                // Log errors
                NSLog(@"[%@ %@ %d]", NSStringFromClass([self class]), NSStringFromSelector(_cmd), __LINE__);
                NSLog(@"Core Data error: %@", error.localizedDescription);
                NSArray *errors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
                if (errors != nil && errors.count > 0) {
                    for (NSError *error in errors) {
                        NSLog(@"  Error: %@", error.userInfo);
                    }
                } else {
                    NSLog(@"  %@", error.userInfo);
                }
                gameDates = nil;
            } else if (game.count) {
                // Array to hold (at most) all the days of the games in the database
                NSMutableArray *days = [[NSMutableArray alloc] initWithCapacity:game.count];
                for (Game *games in game) {
                    // Add only the day to the array
                    [days addObject:[Game convertDateTimetoDay:games.startDateTime]];
                }
    
                // Generate a unique set of dates
                NSSet *uniqueDays = [NSSet setWithArray:days];
                // Create an array from the unique set
                NSMutableArray *uniqueGameDays = [NSMutableArray arrayWithArray:[uniqueDays allObjects]];
                // Create the sort descriptor
                NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
    
                // Sort the array
                NSArray *sortedUniqueGameDays = [uniqueGameDays sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortOrder]];
    
                gameDates = [sortedUniqueGameDays copy];
            } else {
                gameDates = nil;
            }
        }];
    
        return gameDates;
    }
    
    + (NSDate *)convertDateTimetoDay:(NSDate *)dateTimeToConvert {
    
        // Get the year, month and day components (included era although this only applies to BCE)
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTimeToConvert];
        // Add the date with only the selected components to the array
        return [[[NSCalendar currentCalendar] dateFromComponents:components] dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT]];
    }
    

    从iOS 8开始,您可以对Swift使用
    NSCalendar

    一种方法是使用集合:

     let array = ["15-06-2017", "15-08-2017", "15-06-2017", "14-06-2017", 
                  "14-06-2017"]
        let unique = Array(Set(array))
        // ["15-06-2017", "15-08-2017", "14-06-2017"]
    
    您还可以创建一个扩展来更明确地过滤数组:

     extension Array where Element : Equatable {
        var unique: [Element] {
            var uniqueValues: [Element] = []
            forEach { item in
                if !uniqueValues.contains(item) {
                    uniqueValues += [item]
                }
            }
            return uniqueValues
        }
    }
    

    唯一数组将按未指定的顺序排列,您可能需要对其进行排序。有时候最好自己枚举,你可以编写一个扩展

    做一个扩展可能会更好:

    extension Array where Element : Hashable {
        var unique: [Element] {
            return Array(Set(self))
        }
    }
    

    可能有更优化的方法来做你想做的事情,但这种方法既快捷又简单。

    如果用户旅行到不同的时区,这种方法将被打破
    NSDate
    始终存储一个完整的时间,即使您对其进行操作,使某些值为零。它实际上只是
    NSTimeInterval
    的包装,存储自引用日期起的秒数。如果您坚持使用UTC而不是本地时区,这可能没问题。谢谢!为我工作!我不知道应该在哪里添加NSDate+Utils.m,我需要相同的来获得唯一的年份。使用dateWithoutTime方法创建Utils类别。在您的例子中,
    NSDateComponents*components=[calendar components:NSYearCalendarUnit fromDate:self]@Sauvage您知道这行代码中使用的技术描述吗NSString*key=@“date.dateWithoutTime”;您在类别中创建的方法似乎在这里被调用。这项技术有名字吗?我不确定它有名字。我们按日期将所有物体分成若干部分。使用这种方法,我们可以为每一个都设定特定的值。