使用表格视图将两个属性的信息添加到单个核心数据实体中的有效方法

Posted

技术标签:

【中文标题】使用表格视图将两个属性的信息添加到单个核心数据实体中的有效方法【英文标题】:An Efficient Way to Add Two Attributes' Information Into a Single Core Data Entity with a Table View 【发布时间】:2013-11-21 16:55:00 【问题描述】:

我有一个基本的 App Premise - 允许用户使用 FetchedResultsController 和 Core Data 向 4 个文本字段提供信息,并在表格视图中准确显示该信息。

我无法正确更新具有两个属性的实体。

我的实体是: 事务(isGiven 属性)

场合(dateOfEvent、标题属性)

人物(姓名属性)

项目(itemType 属性)。

Person 和 Item 在这里无关紧要。在 View Controller 的 Save Method 中,我调用我的 Occasion 类,将输入的 dateOfEvent 和标题传递给它。在这堂课中,我想要实现的是:

检查标题是否存在。如果没有,请创建一个。如果是,请将其退回。 检查日期是否存在。如果没有,请创建一个。如果是,请将其退回。

日期当前是一个字符串(稍后将更改为 NSDate - 我首先对此进行测试)。

我创建了一个复杂的 If 语句,但它只是没有适当地更新表视图。让我们看一些代码:

场合

+ (Occasion *)occasionWithTitle:(NSString *)title andEnteredDate:(NSString *)date inManagedObjectContext:(NSManagedObjectContext *)context

    Occasion *occasion = nil;

    // Creating a fetch request to check whether the name of the person already exists
    NSFetchRequest *eventRequest = [NSFetchRequest fetchRequestWithEntityName:@"Occasion"];
    eventRequest.predicate = [NSPredicate predicateWithFormat:@"title = %@", title];
    NSSortDescriptor *eventSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES];
    eventRequest.sortDescriptors = [NSArray arrayWithObject:eventSortDescriptor];
    NSFetchRequest *dateRequest = [NSFetchRequest fetchRequestWithEntityName:@"Occasion"];
    dateRequest.predicate = [NSPredicate predicateWithFormat:@"dateOfEvent = %@", date];
    NSSortDescriptor *dateSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"dateOfEvent" ascending:YES];
    dateRequest.sortDescriptors = [NSArray arrayWithObject:dateSortDescriptor];
    NSError *error = nil;
    NSArray *occasions = [context executeFetchRequest:eventRequest error:&error];
    NSArray *dates = [context executeFetchRequest:dateRequest error:&error];

    if (occasions)
    

        if ([occasions count] == 0)
        
            occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" inManagedObjectContext:context];
            occasion.title = title;
            if ([dates count] == 0)
            
                occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" inManagedObjectContext:context];
                occasion.dateOfEvent = date;
            
            else
            
                occasion = [dates lastObject];
            
        
        else
        
            occasion = [occasions lastObject];
            if ([dates count] == 0)
            
                occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" inManagedObjectContext:context];
                occasion.dateOfEvent = date;
            
            else
            
                occasion = [dates lastObject];
            
         
    
    else
    
        // handle error
    
    return occasion;

调用这个的保存方法是:

Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context];
Occasion *enteredOccasion = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text andEnteredDate:self.dateTextField.text inManagedObjectContext:context];
transaction.occasion = enteredOccasion;

TableView 中仅显示“场合名称”的 fetchRequest 是:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Occasion" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;    
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"dateOfEvent" ascending:NO];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];

当我选择一个场合名称时,我会转到另一个控制器,它会向我显示有关该场合的所有信息,包括人名、金额(与交易实体相关的东西),所以我的 fetchRequest 是:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;    
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"occasion.dateOfEvent" ascending:NO];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"occasion.dateOfEvent" cacheName:nil];

我知道 Occasion if 语句不太对劲 - 也许我只需要一个 insertNewObjectForEntityForName 因为它会在表格视图中创建各种不准确的结果 - 比如创建多个场合、日期等。

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

您的if 语句逻辑错误。你只需要一个insertNewObjectForEntityForName 以避免重复。

仅当titledateOfEvent 不存在时才创建Occasion 逻辑应该是:

NSFetchRequest *r = [NSFetchRequest fetchRequestWithEntityName:@"Occasion"];
r.predicate = [NSPredicate predicateWithFormat:@"title = %@ OR dateOfEvent = %@", title,date];
NSArray *matched = [context executeFetchRequest:eventRequest error:&error];

if (matched) 
    if ([matched count] == 0) 
        occasion = [NSEntityDescription insertNewObjectForEntityForName:@"Occasion" 
                                                 inManagedObjectContext:context];
        occasion.dateOfEvent = date;
        occasion.title = title
     else 
        occasion = [matched lastObject];
     
 else 
    // handle error

这意味着特定日期或标题只允许出现一次,这在现实世界中没有多大意义。 如果您想确保该dateOfEventtitle 的事件不存在,只需将OR 替换为AND

注意:我的解决方案没有考虑到,如果发现现有场合,它就是与 title 匹配的场合(我认为这无关紧要)。

编辑: 在阅读了您的 cmets 后,我不太清楚您要完成什么?

如果您需要 Occasion 实体在标题上是唯一的(按标题对事件进行分组),并且有多个日期,则需要更改模型以支持此功能。

使用date(以及发生事件所需的任何其他属性)将OccasionOccurrence 实体添加到您的模型中。 而不是 date 实体上的 date 属性添加到 OccasionOccurrence 的一对多关系

现在,在创建 OccasionOccurrence(而不是 Occasion)时,检查是否存在以下记录:

NSFetchRequest *r = [NSFetchRequest fetchRequestWithEntityName:@"OccasionOccurrence"];
r.predicate = [NSPredicate predicateWithFormat:@"occasion.title = %@ AND dateOfEvent = %@", title,date];

如果 fetch 返回的结果不是重复事件(或者如果您在同一天有很多生日,则不是)。

如您所见,不清楚您要完成什么。

【讨论】:

非常感谢您的回复——这真的很有道理,因为我认为我的整个“场合”课程都非常错误——这真的很有帮助。如您所述,我将其更改为 AND 语句,它没有找到匹配的事件.. 所以使用上面的确切代码,但是使用 AND,如果我添加事务 1 与 Occasion Birthday 和今天的日期,保存它,一切都很好. 如果我添加另一个条目,其中包含生日和今天的日期(不同的人),它可以工作并且一切都很好。当我添加一个包含生日的新交易,但与昨天不同的日期时,它会在表格视图中生成两个单独的生日对象。第一个具有最新的交易,另一个具有另外两个交易 - 有没有办法稍微修改代码,使其检查“如果事件存在,则返回它。如果日期存在,则返回它。如果两者都不存在,则创建两者,如果存在,则创建它但返回另一个等等?我只是想确定我摆脱了表格视图中的任何重复项 看起来它只是在执行您的最后一条语句:注意:我的解决方案没有考虑到,如果找到现有的场合,它就是与标题匹配的场合(我认为这无关紧要)。 - 我觉得只有一两行的距离 @amitsbajaj 我已经编辑了我的问题,但仍然不清楚你要完成什么。请提供有关您的任务的更多信息 感谢 Dan 的更新,并对造成的混乱表示歉意。如果它已经存在,我只想能够返回一个现有的 Occasion,或者如果它不存在则创建一个新的。我希望日期也一样;如果存在则返回现有的,如果不存在则创建新的。但也是两者的结合;可能有一个现有的日期,但有一个新的场合,或者一个现有的场合和一个新的日期。我想要那种灵活性,没有重复......这可能吗?我希望这是有道理的 - 再次感谢

以上是关于使用表格视图将两个属性的信息添加到单个核心数据实体中的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

将表格视图单元格中的数据保存在核心数据中

按两个依赖属性对核心数据实体进行排序

如何将第二个表格视图的值与第一个表格视图的单击行的关系分开?

如何将来自多个视图控制器的数据保存到单个核心数据实体中

向核心数据实体添加属性

根据日期添加核心数据属性