Reputation: 1304
I have a basic App Premise - allow the user to information to 4 text fields and have that information accurately displayed in a Table View, using FetchedResultsController and Core Data.
I have a problem getting one entity with two attributes to update appropriately.
My entities are: Transaction (isGiven attribute)
Occasion (dateOfEvent, title attributes)
Person (name attribute)
Item (itemType attribute).
Person and Item do not matter here. In the Save Method of the View Controller, I call my Occasion class, pass it the entered dateOfEvent and title. In this class, what I want to achieve is:
The date is currently a string (which will be changed to a NSDate later - I'm testing this out first).
I have created a complex If statement, but it's just not updating the Table view appropriately. Let's look at some code:
Occasion
+ (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;
}
The save method calling this is:
Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:context];
Occasion *enteredOccasion = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text andEnteredDate:self.dateTextField.text inManagedObjectContext:context];
transaction.occasion = enteredOccasion;
The fetchRequest in the TableView showing just the "Occasion Names" is:
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Occasion" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"dateOfEvent" ascending:NO];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
When I select an Occasion Name, I get segued over to another controller which shows me all information about that occasion, including Person names, amounts (things related from the Transaction Entity), so my fetchRequest is:
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];
I know something is not quite right with the Occasion if statements - perhaps I only need one insertNewObjectForEntityForName because it's creating all sorts of inaccurate results in the Table View - like creating multiple occasions, dates, etc.
Any help would be appreciated!
Upvotes: 0
Views: 110
Reputation: 6011
Your if
statement logic is wrong. you do need only one insertNewObjectForEntityForName
to avoid duplications.
To create an Occasion
only if one does not exist with that title
OR dateOfEvent
the logic should be:
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
}
This mean that only one occasion is allowed for a specific date OR title, which does not make a lot of sense in the real world.
If you want to make sure that an event does not already exist for that dateOfEvent
AND title
, simply replace the OR
with AND
Note: my solution does not take into account that if an existing occasion is found it is the one matching the title
(I assumed it does not matter).
Edit:
After reading your comments, it is not quite clear to me what is it you try to accomplish?
If you need your Occasion
entity to be unique on the title (group occasion occurrences by title), and have many dates you will need to change your model in order to support this functionality.
Add an OccasionOccurrence
entity to your model with a date
(and any other attribute you need for the occurrence).
instead of your date
attribute on your Occasion
entity add a to-many relationship to OccasionOccurrence
now, when creating an OccasionOccurrence
(instead of Occasion
) check if any records exist for:
NSFetchRequest *r = [NSFetchRequest fetchRequestWithEntityName:@"OccasionOccurrence"];
r.predicate = [NSPredicate predicateWithFormat:@"occasion.title = %@ AND dateOfEvent = %@", title,date];
if the fetch return any results than this is a duplicated event (or not if you have many birthdays on the same day).
As you can see, it is not clear what are you trying to accomplish.
Upvotes: 1