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

我遇到一个具有两个属性的实体要适当更新的问题。

我的实体是:
交易(isGiven属性)

场合(dateOfEvent,标题属性)

人(名称属性)

项目(itemType属性)。

这里的人员和项目都无关紧要。在视图控制器的Save方法中,我调用了Occasion类,并将输入的dateOfEvent和标题传递给它。在本课程中,我想要实现的是:


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


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

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

场合

+ (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;
}


调用此方法的save方法是:

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,因为它在表视图中创建各种不准确的结果-例如创建多个场合,日期等。

任何帮助,将不胜感激!

最佳答案

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

仅在Occasiontitle不存在的情况下创建一个dateOfEvent
逻辑应为:

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匹配的场合(我认为这没有关系)。

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

如果您需要Occasion实体在标题上是唯一的(按标题分组发生的场合),并且有很多日期,则需要更改模型以支持此功能。

使用OccasionOccurrence(以及发生时所需的任何其他属性)将date实体添加到模型中。
代替date实体上的Occasion属性,向OccasionOccurrence添加一对多关系

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

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


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

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

10-08 13:13