iOS核心数据 - 在编辑对象后立即取出任何内容

时间:2013-04-15 18:43:02

标签: ios core-data uiviewcontroller nsfetchrequest

在使用CoreData更新对象后立即获取数据时出现以下问题。

以下是我遇到的问题的一些细节:

  • 我有一个“PersonDetailsViewController”,其中有2个包含一些人信息的表视图(每个Person对象都添加到CoreData上下文中,其中包含一个名称和一组电子邮件)。
  • tablewiews的每一行都是可点击的,并且会转换为模式VC(“EditDetailsVC”),让用户更新此人的信息。
  • 在通过CoreData上下文中的托管对象更新信息后,“EditDetailsVC”上的“done”返回“PersonDetailsVC”。
  • 在“PersonsDetailsVC”的 viewDidLoad viewWillAppear中,我取回了此人的信息并填充了tableviews。

最后一步是事情没有以正确的方式发生:有时候,从数据库中正确检索到Person对象,有时候什么都没有被提取。

我在更新对象后尝试保存上下文,但发生了同样的问题。

我认为这与访问数据库的时间有关,也许当我尝试在上下文中获取某些数据时,数据被写入上下文?

你能帮助我吗?

编辑:

以下所有属于名为“DataManager”的类,它集中了所有CoreData访问。 该类使用单例设计模式。

@property (nonatomic,strong) NSManagedObjectContext * context ;
#define DM_CONTEXT      [DataManager sharedInstance].context;

以下是viewWillAppear中调用的方法:

+(NSDictionary*) getTargetDetailsForIdentifier:(NSNumber*)identifier
{

    NSMutableDictionary * targetDetails ;

    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Target"];
    NSPredicate * predicate  = [NSPredicate predicateWithFormat:@"identifier =%@",identifier];
    request.predicate = predicate ;

    NSError * err ;

    NSArray * result = [DM_CONTEXT executeFetchRequest:request error:&err];

    if(err)
    {
        NSLog(@"%s : Error when fetching target details for the identifier <%@>",__PRETTY_FUNCTION__,identifier);
    }
    else if(![result count])
    {
        NSLog(@"%s : Nothing found for the identifier <%@>",__PRETTY_FUNCTION__,identifier);

    }
    else if([result count] > 1)
    {
        NSLog(@"%s : Error more than 1 target corresponding to the identifier <%@>",__PRETTY_FUNCTION__,identifier);
    }
    else
    {
        NSLog(@"%s : Target details successfully fetched for identifier <%@>",__PRETTY_FUNCTION__,identifier);

        targetDetails = [[NSMutableDictionary alloc] init];

        Target * target = [result lastObject];

        [targetDetails setObject:target.firstname  forKey:FIRSTNAME_KEY];
        [targetDetails setObject:target.lastname   forKey:LASTNAME_KEY];
        [targetDetails setObject:target.rank       forKey:RANK_KEY];
        [targetDetails setObject:target.identifier forKey:IDENTIFIER_KEY];

        if(target.photoData)
        {
            [targetDetails setObject:target.photoData  forKey:PHOTODATA_KEY];
        }

        NSSet * emailSet = [[NSSet alloc] initWithSet:target.emailList];
        NSSet * phoneSet = [[NSSet alloc] initWithSet:target.phoneList];

        [targetDetails setObject:emailSet forKey:EMAILS_KEY];
        [targetDetails setObject:phoneSet forKey:PHONES_KEY];
    }

    return targetDetails ;

}

以下是更新方法的片段。在这里,我只显示更新使用唯一编号标识的人的电子邮件地址的部分:

+(void) replaceObject:(id)object withObject:(id)newObject forKey:(NSString*)key forIdentifier:(NSNumber*)identifier
{
    if([key isEqualToString:EMAIL_KEY])
    {
        if([object isKindOfClass:[NSString class]] && [newObject isKindOfClass:[NSString class]])
        {
            NSString * email    = (NSString *)object;
            NSString * newEmail = (NSString *)newObject;

            NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Email"];
            NSPredicate * predicate = [NSPredicate predicateWithFormat:@"(email =%@) AND (emailOwner.identifier=%@)",email,identifier];

            request.predicate = predicate ;

            NSError * err ;

            NSArray * result = [DM_CONTEXT executeFetchRequest:request error:&err];

            if(err)
            {
                NSLog(@"%s : Error when fetching the email object to be removed for target identifier <%@>",__PRETTY_FUNCTION__,identifier);
            }
            else if(![result count])
            {
                NSLog(@"%s : Nothing found.",__PRETTY_FUNCTION__);
            }
            else if([result count] > 1)
            {
                NSLog(@"%s : Error. More than 1 email object fetched for target identifier <%@>",__PRETTY_FUNCTION__,identifier);
            }
            else
            {
                Email * emailToUpdate = [result lastObject];
                emailToUpdate.email = newEmail ;

                if (![DM_CONTEXT save:nil])
                {
                    NSLog(@"%s : Can't Save after updating email! for the identifier <%@>",__PRETTY_FUNCTION__,identifier);

                }
                else
                {
                    NSLog(@"%s : Email successfully updated.",__PRETTY_FUNCTION__);
                }
            }
        }
        else
        {
            NSLog(@"%s : Nothing to replace, or bad objects.",__PRETTY_FUNCTION__);
        }
    }

}

问题在于,每次更新此人的信息后,当我返回viewWillAppear时,getTargetDetailsForIdentifier:将不会返回任何内容(结果数组为空)。

1 个答案:

答案 0 :(得分:2)

  

返回“PersonDetailsVC”...在“PersonsDetailsVC”的viewDidLoad中,我取回了该人的信息并填充了tableviews。

好的,但这没有任何意义。在视图控制器的生命周期中,viewDidLoad仅被称为一次。当你从模态视图控制器返回时,你不能用它来“取回人的信息”;它甚至没有被召唤。

您应该在viewWillAppearviewDidAppear进行此类工作。

如果从模态视图控制器返回时调用viewDidLoad ,那么您的架构也会出现问题,即您没有“返回”但是创建了一个全新的查看控制器,这也是错误的。