iOS 核心数据 - 编辑对象后没有立即获取任何内容

Posted

技术标签:

【中文标题】iOS 核心数据 - 编辑对象后没有立即获取任何内容【英文标题】:iOS Core data - Nothing fetched right after an object is edited 【发布时间】:2013-04-15 18:43:02 【问题描述】:

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

以下是我遇到的问题的一些详细信息:

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

在最后一步,事情没有以正确的方式发生:有时从数据库中正确检索到 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 ;


这里是更新方法的sn-p。在这里,我只展示了更新具有唯一编号的人的电子邮件地址的部分:

+(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】:

返回到 "PersonDetailsVC" ... 在 "PersonsDetailsVC" 的 viewDidLoad 中,我取回人员的信息并填充表格视图。

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

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

如果viewDidLoad 在您从模态视图控制器返回时被调用,那么您的架构也存在问题,即您不是“返回”而是创建一个全新的视图控制器,这也是错误的。

【讨论】:

好的,所以如果您需要更多帮助,您可能应该显示一些代码。

以上是关于iOS 核心数据 - 编辑对象后没有立即获取任何内容的主要内容,如果未能解决你的问题,请参考以下文章

我正在尝试使用 NSFetchedResultController 从核心数据中获取对象,但它没有在 tableview 中显示任何数据

Swift 3 / iOS 10,正确使用核心数据

快速更新核心数据对象 3

从核心数据中获取数据

核心数据:SQLite 没有立即更新

如何将获取的对象保存到核心数据