向 coreData 中的实体添加浮点属性,并在每次添加新对象时递增它

Posted

技术标签:

【中文标题】向 coreData 中的实体添加浮点属性,并在每次添加新对象时递增它【英文标题】:Adding a float attribute to an entity in coreData and increment it on every addition of new Object 【发布时间】:2012-11-06 06:55:20 【问题描述】:

我是 coreData 的新手,我正在开发一个示例应用程序,在该示例应用程序中,我向名为“Test”的实体添加了一个名为 displayOrder 的浮点类型属性。我想在添加每个测试对象时增加这个显示顺序。为此,我编写了以下代码,但它不起作用,我想知道我哪里出错了

- (void)insertNewObject:(NSString *)fileName
    
    Test *testName = [NSEntityDescription insertNewObjectForEntityForName:@"Test" inManagedObjectContext:self.managedObjectContext];

    [testName setName:fileName];

    NSManagedObject *lastObject = [self.controller.fetchedObjects lastObject];
    float lastObjectDisplayOrder = [[lastObject valueForKey:@"displayOrder"] floatValue];
    NSLog(@"%f",lastObjectDisplayOrder);
    [testName setValue:[NSNumber numberWithDouble:lastObjectDisplayOrder + 1.0] forKey:@"displayOrder"];

    // Save the context.
    NSError *error = nil;
    if (![self.managedObjectContext save:&error]) 
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    

实际上,问题是它第一次递增,即从 0 到 1,但之后我总是得到 1。

问候 兰吉特

【问题讨论】:

NSLog(@"%f",lastObjectDisplayOrder); 怎么样?是否总是打印0 嗨@Aadhira,第一次是0 第二次是1,后来总是1 你能在你的获取结果控制器上显示排序描述符吗?似乎fetchedObjects lastObject 总是为`lastObjectDisplayOrder'返回值为1的对象 嗨@ChrisH,我想通了,现在假设,如果我想要objectAtIndex:0,而不是获取lastObject,我得到错误说明,arrayOutofbound index 如果您在数组的索引 0 处请求一个对象,并得到一个超出范围的错误,这意味着您的数组是空的。无论哪种方式,我都会说您的问题是您正在根据数组中错误对象的值增加lastObjectDisplayOrder。如果数字与数组计数相同,为什么不将其用作您增加的值? 【参考方案1】:

您的问题可能与您加载 lastObject 的部分有关,并且您可能没有更新 fetchedresultscontroller,我建议创建一个 iVar 并在 init 或 viewDidLoad 上分配值,然后使用该 iVar 更新并获取正确的值,另外,如果您不为此使用小数,而您只需要顺序,那么 Integer 应该会更好。

【讨论】:

当我插入新对象时,我取消隐藏一个新的 ViewController,我在其中添加了对象的名称,然后我隐藏了 ViewController。所以我添加了iVar并在ViewDidLoad中获取了lastObject,然后它不可能因为它没有被调用,因为我只是隐藏了ViewController【参考方案2】:

您可以使用核心数据聚合函数来获得最大的 displayOrder 值。

类似:

- (NSNumber *)nextDisplayOrder 
    NSManagedObjectContext *context = self.managedObjectContext;

    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Test" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDescription];
    [request setResultType:NSDictionaryResultType];

    NSExpression *keyExpression = [NSExpression expressionForKeyPath:@"displayOrder"];
    NSExpression *maxExpression = [NSExpression expressionForFunction:@"max:" arguments:[NSArray arrayWithObject:keyExpression]];

    NSExpressionDescription *description = [[NSExpressionDescription alloc] init];
    [description setName:@"maxDisplayOrder"];
    [description setExpression:maxExpression];
    [description setExpressionResultType:NSFloatAttributeType];

    [request setPropertiesToFetch:[NSArray arrayWithObject:description]];

    NSError *error = nil;
    NSArray *results = [context executeFetchRequest:request error:&error];
    if (results.count == 1) 
        NSNumber *maxDisplayOrder = [[results objectAtIndex:0] valueForKey:@"displayOrder"];
        return [NSNumber numberWithFloat:[maxDisplayOrder floatValue] + 1.f];
     else 
        NSLog(@"Could not get next displayOrder. Error: %@", error);
    

    return nil;

一些补充说明:

对于像 displayOrder 这样的离散值使用整数而不是浮点数 这个样板代码可以用MagicalRecord写成两行,所以你可能想看看 more info on aggregate functions

【讨论】:

不确定。这里有很多未知数,而我发布的代码在任何情况下都应该可以工作,只要您在每次插入后保存 MOC 即可。您是否在每次插入调用之前重新加载 self.controller ?您是否按 displayOrder(获取请求的适当排序描述符)对对象进行排序? NSLog self.controller.fetchedObjects 并查看您的对象的外观。您还混合了 NSNumber double 和 float 方法,尽管这可能不是这里的问题。你真的应该为这个属性使用整数,我建议你改变模型。 是的,我正在按 displayOrder 对对象进行排序。如何使用您的函数,这是将值传递给属性的正确方法 [test setdisplayOrder:[self nextDisplayOrder]; 我正在尝试调用该函数并获取您的函数返回的值,但该函数在 NSArray *results = ... 行崩溃 对不起,我忘记将结果类型设置为 NSDictionaryResultType。现在应该没问题了。 我的代码也在工作,问题是我按降序排序。所以他们不需要使用魔法记录

以上是关于向 coreData 中的实体添加浮点属性,并在每次添加新对象时递增它的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个类中创建 CoreData 实体并在另一个类中访问?

Core Data 轻量级迁移 - 现有实体是不是添加了新属性?

基于实体属性确保 CoreData 实体唯一的最佳实践

CoreData 向实体行添加新关系

向 coredata 添加新实体 - 我还能使用轻量级迁移吗?

为啥更改实体的属性时会删除我的 CoreData 信息?