对 CoreData 执行添加/更新时出现问题

Posted

技术标签:

【中文标题】对 CoreData 执行添加/更新时出现问题【英文标题】:Issue with performing add/update to CoreData 【发布时间】:2013-07-05 20:10:10 【问题描述】:

我有一个NSArray 持有几个NSDictionary,每次我保存一个NSDictionary 对象并将其添加到NSArray 时,我都会将它发送到添加/更新函数。 我知道我读取的数据是正确的,当我使用没有更新功能的情况下添加数据时,所有数据都插入到CoreData,但我想添加更新功能来验证我放入的数据。 现在,该函数添加第一个对象,然后一遍又一遍地转到“更新”。 怎么了?

我的代码:

-(void)updateOrAddTrap:(NSMutableDictionary*)trapObject

    NSInteger trapID = [trapObject[@"id"] integerValue];
    Trap *trapEntity = nil;
    NSError *error = nil;
    Boolean success = true;

    self.fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Trap"];
    self.predicate = [NSPredicate predicateWithFormat:@"trapID == %d", trapID];
    [self.fetchRequest setPredicate:self.predicate];

    NSArray *results = [self.managedObjectContext executeFetchRequest:self.fetchRequest error:&error];
    if (results == nil)
    
        // Handle error
        NSLog(@"HANDLE ERROR");
        success = false;
    
    else if ([results count] == 0)
    
        // Nothing to update, add new trap
        NSLog(@"NOTHING TO UPDATE | ADD NEW");

        // Create a new record (row)
        trapEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Trap" inManagedObjectContext:self.managedObjectContext];
    
    else
    
        NSLog(@"UPDATE EXISTING OBJECT");
        trapEntity = results[0]; // There should be only one object for the ID.
    


    if (trapEntity != nil)
    
        // Set properties for new or existing object ...

        // Int
        int alarmDistance = [[trapObject objectForKey:ALARMDISTANCE] intValue];
        int type = [[trapObject objectForKey:TYPE] intValue];
        int roadNumber = [[trapObject objectForKey:ROADNUMBER] intValue];
        int trap_id = [[trapObject objectForKey:ID] intValue];
        int polys = [[trapObject objectForKey:POLYGONS] intValue];
        int degrees = [[trapObject objectForKey:DEGREES] intValue];
        [trapEntity setAlarmDistance:[NSNumber numberWithInt:alarmDistance]];
        [trapEntity setType:[NSNumber numberWithInt:type]];
        [trapEntity setRoadNumber:[NSNumber numberWithInt:roadNumber]];
        [trapEntity setTrapID:[NSNumber numberWithInt:trap_id]];
        [trapEntity setPolys:[NSNumber numberWithInt:polys]];
        [trapEntity setDegrees:[NSNumber numberWithInt:degrees]];

        // Boolean
        BOOL isActive = [[trapObject objectForKey:ISACTIVE] integerValue] == 1 ? YES : NO;
        [trapEntity setIsActive:[NSNumber numberWithBool:isActive]];

        // Float
        float lat = [[trapObject objectForKey:LAT] floatValue];
        float lon = [[trapObject objectForKey:LON] floatValue];
        [trapEntity setLat:[NSNumber numberWithFloat:lat]];
        [trapEntity setLon:[NSNumber numberWithFloat:lon]];

        // NSString
        [trapEntity setDirection:[trapObject objectForKey:DIRECTION]];
        [trapEntity setTrapDescription:[trapObject objectForKey:DESCRIPTION]];
        [trapEntity setPoly0:[trapObject objectForKey:POLYGON_A]];
        [trapEntity setPoly1:[trapObject objectForKey:POLYGON_B]];
        [trapEntity setPoly2:[trapObject objectForKey:POLYGON_C]];
        [trapEntity setPolygonAzimut1:[trapObject objectForKey:POLYGON_A_AZIMUTH]];
        [trapEntity setPolygonAzimut2:[trapObject objectForKey:POLYGON_B_AZIMUTH]];
        [trapEntity setPolygonAzimut3:[trapObject objectForKey:POLYGON_C_AZIMUTH]];
        // etc. for all properties ...

        if (![self.managedObjectContext save:&error])
        
            NSLog(@"HANDLE ERROR WHEN SAVING THE OBJECT");
            success = false;
        
    

我很高兴知道如何正确更新,因为我现在也缺少此功能。

编辑: 多亏了马丁,代码就像一个魅力。

【问题讨论】:

你说“现在,函数添加第一个对象,然后一遍又一遍地转到'更新'”你的更新函数在哪里? 更新应该在'if (success)'中,因为不知道怎么做,我还没有构建。 【参考方案1】:

我不确定这是否是您的问题的原因,但您正在检查错误 条件或空结果是错误的。应该是

BOOL success = true;
Trap *trap = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:self.fetchRequest error:&error];
if (results == nil) 
    NSLog(@"HANDLE ERROR");
    success = false;
 else if ([results count] == 0) 
    NSLog(@"NOTHING TO UPDATE | ADD NEW");
    trap = [NSEntityDescription insertNewObjectForEntityForName:@"Trap" inManagedObjectContext:self.managedObjectContext];
 else 
    NSLog(@"UPDATE EXISTING OBJECT");
    trap = result[0]; // There should be only one object for the ID.

if (trap != nil) 
    // Set properties for new or existing object ...
    [trap setTrapID:[NSNumber numberWithInt:trap_id]];
    // etc. for all properties ...

    if (![self.managedObjectContext save:&error]) 
        NSLog(@"HANDLE ERROR WHEN SAVING THE OBJECT");
        success = false;
    

executeFetchRequest 返回

nil 如果发生错误,并且 如果未找到匹配对象,则为空数组。

【讨论】:

像魅力一样工作,谢谢!你能帮我如何更新/修改? 'trapObject' 每次都不同。 感谢您的帮助!我用你的答案编辑了代码。我第一次得到“没什么可更新的 | ADD NEW',其余时间我得到'UPDATE EXISTING OBJECT',然后用户界面卡住了,我在数据库中只看到一条记录。 @IdanMoshe:抱歉,但我不知道您的 UI 为何会卡住 :-) 请注意,您应该从代码中删除旧的 trapEntity = [[self.managedObjectContext executeFetchRequest:self.fetchRequest error:&error] lastObject]; 行。 奇怪。也许在调试器中单步执行并检查会发生什么。建议:验证int trap_id = ... 是否分配了正确的值。 (ID 是否与 @"trapID" 相同?)。 NSLog 谓词和获取请求。 NSLog 新创建的 Trap 对象,检查 ID 是否设置正确。

以上是关于对 CoreData 执行添加/更新时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSPredicate 从 NSFetchedResultscontroller 更新 NSManagedObject 时出现 CoreData 错误

添加到 coredata 数组时出现类型不匹配问题

将新对象添加到 CoreData 应用程序时出现问题

集成 RestKit 和 MagicalRecord 时出现 CoreData 轻量级迁移错误

在 iOS 中对来自 Core Data 的实体的 NSArray 进行快速枚举时出现运行时错误

将 Core Data 添加到现有 Xcode 项目时出现未声明的标识符错误