I have a Core Data to-many relationship that looks like this:
Athlete(evals)<->>Eval(whosEval)
I have a table view for Athletes which displays ALL the Athletes in the database. I want to set the subtitle text to a Eval attribute, let's say it is called "date_recorded" the problem is, there could be more than 1 eval for each Athlete. I need to select the last object in the evalArray, and then display the correlating Eval attribute for each Athlete, so each Athlete's subtitle text will probably be different. How would I do this for every cell in my table? Here is what i've got so far:
allathletes.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Athlete Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Athlete *athlete = (Athlete *)[athleteArray objectAtIndex:indexPath.row];
cell.textLabel.text =[athlete full];
cell.detailTextLabel.text = //eval attribute "date_recorded"
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSFetchRequest *athleteRequest = [[NSFetchRequest alloc] init];
[athleteRequest setEntity:[NSEntityDescription entityForName:#"Athlete" inManagedObjectContext:_managedObjectContext]];
NSError *athleteError = nil;
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %#", athlete.full];
[athleteRequest setPredicate:athletePredicate];
NSArray *results = [_managedObjectContext executeFetchRequest:athleteRequest error:&athleteError];
Athlete *currentAthlete = [results objectAtIndex:0];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosEval == %#", currentAthlete];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Eval" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"date_recorded"
ascending:NO
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil){
//handle error
}
NSMutableArray *lastEvalArray = mutableFetchResults;
Eval *lastEval = lastEvalArray.lastObject;
cell.detailTextLabel.text = lastEval.date_recorded;
return cell;
}
If date_recorded is an NSDate attribute, then you can just do
Athlete *athlete = (Athlete *)[athleteArray objectAtIndex:indexPath.row];
NSDate *lastRecorded = [athlete valueForKeyPath:#"#max.evals.date_recorded"];
and then use a NSDateFormatter to convert lastRecorded to an NSString and
assign it to cell.detailTextLabel.text.
Related
I am new in iPhone Application Development. I am working on chat app in iOS using XMPP and Ejabberd. But I am not able to delete the chat of particular user (not a single message).
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[self DeleteMessageChat:indexPath];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[messages removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
-(void)DeleteMessageChat :(NSIndexPath *)indexpath
{
self.cls=[self.arrProfile objectAtIndex:indexpath.row];
NSString *userJid = [NSString stringWithFormat:#"%#%#",self.cls.UserId,Xmppserver];
XMPPMessageArchivingCoreDataStorage *storage = appDelegate.xmppMessageArchivingStorage;
NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entityDescription];
NSString *predicateFrmt = #"bareJidStr == %#";
NSError *error;
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, userJid];
request.predicate = predicate;
NSArray *messages_new = [moc executeFetchRequest:request error:&error];
NSManagedObject *obj=[messages_new objectAtIndex:indexpath.row];
[moc deleteObject:obj];
error = nil;
if (![moc save:&error])
{
NSLog(#"Error deleting movie, %#", [error userInfo]);
}
}
Please help me to solved this problem.
I did this in my code. Try to edit according to you arrays.
NSString *userJid = [NSString stringWithFormat:#"%#%#",cell.frndName.text,DomainName];
NSString *userJid1= [NSString stringWithFormat:#"%#%#",[[NSUserDefaults standardUserDefaults]valueForKey:#"name"],DomainName];
NSFetchRequest *messagesCoreD = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context=[[self appDelegate].xmppMessageArchivingCoreDataStorage mainThreadManagedObjectContext];
NSEntityDescription *messageEntity = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Contact_CoreDataObject" inManagedObjectContext:context];
[messagesCoreD setEntity:messageEntity];
[messagesCoreD setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSString *predicateFrmt = #"bareJidStr == %#";
NSString *predicateFrmt1 = #"streamBareJidStr == %#";
NSPredicate *predicateName = [NSPredicate predicateWithFormat:predicateFrmt,userJid];
NSPredicate *predicateSSID = [NSPredicate predicateWithFormat:predicateFrmt1,userJid1];
NSArray *subPredicates = [NSArray arrayWithObjects:predicateName, predicateSSID, nil];
NSPredicate *orPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
messagesCoreD.predicate = orPredicate;
NSError * error = nil;
NSArray * messages = [context executeFetchRequest:messagesCoreD error:&error];
//error handling goes here
[tableView reloadData];
for (NSManagedObject * message in messages)
{
[context deleteObject:message];
[tableView reloadData];
}
NSEntityDescription *messageEntity1 = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context];
[messagesCoreD setEntity:messageEntity1];
[messagesCoreD setIncludesPropertyValues:NO]; //only fetch the managedObjectID
messagesCoreD.predicate = orPredicate;
NSArray * messages1 = [context executeFetchRequest:messagesCoreD error:&error];
//error handling goes here
[tableView reloadData];
for (NSManagedObject * message in messages1)
{
[context deleteObject:message];
[tableView reloadData];
}
NSError *saveError = nil;
[context save:&saveError];
I added this code in commitEditingStyle delegate method. Here you pass friend name in userJid and logged in user name in userJid1.
I am using Core Data and UITableViewController. I have a table category with columns name, descript and is_active (boolean).
I want to fetch results like
SELECT *
FROM CATEGORY
WHERE IS_ACTIVE = 1
I have made this active through a form.
I am trying this code - in view I have this load section
- (void)viewDidLoad
{
[super viewDidLoad];
IMSAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
context = [appDelegate managedObjectContext];
NSEntityDescription *category = [NSEntityDescription entityForName:#"Category" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:category];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *srotDesc = [[NSArray alloc]initWithObjects:sort, nil];
[request setSortDescriptors:srotDesc];
NSError *error;
NSMutableArray *results = [[context executeFetchRequest:request error:&error] mutableCopy];
if (results == nil) {
//error handle here
}
[self setArr:results];
NSLog(#"there is category array");
[self.tableView reloadData];
[arr count];
}
And In tableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Category *category = [arr objectAtIndex:indexPath.row];
// Configure the cell...
cell.textLabel.text = [category name];
cell.detailTextLabel.text = [category descript];
return cell;
}
It is showing all the records to me like all the name and the description.
I want to show those records only where is_active = 1.
Add a predicate to your NSFetchRequest
...
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:category];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"is_active == 1"];
[request setPredicate:predicate];
...
I have a to-many relationship between 2 entities. Athlete(evals)<-->>Eval(whosEval). I am trying to display only the evals of the athlete who was selected. However, when I try to access the relationship through eval.whosEval, I get an undefined error. When I run the app, the table is empty, whereas if I comment out the predicate, it displays ALL Evals for ALL the Athletes. Am I missing something? Thank you.
allEvals.m
-(void)viewWillAppear:(BOOL)animated{
self.title = [NSString stringWithFormat:#"%#'s Evaluations",_athletesFullName];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSFetchRequest *athleteRequest = [[NSFetchRequest alloc] init];
[athleteRequest setEntity:[NSEntityDescription entityForName:#"Athlete" inManagedObjectContext:_managedObjectContext]];
NSError *athleteError = nil;
NSArray *results = [_managedObjectContext executeFetchRequest:athleteRequest error:&athleteError];
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %#", _athletesFullName];
[request setPredicate:athletePredicate];
Athlete *currentAthlete = [results objectAtIndex:0];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosEval == %#", currentAthlete];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Eval" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"date_recorded"
ascending:NO
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil){
//handle error
}
[self setEvalArray:mutableFetchResults];
[self.tableView reloadData];
NSLog(#"Athlete's Full Name is: %#",_athletesFullName);
}
Your predicate uses the athlete name when it should really use the athlete object:
#"whosEval == %#", self.athlete
You call
NSLog(#"This eval is for: %#", eval.whosEval);
But you declared eval as:
NSEntityDescription *eval = ...
So there is no way that class NSEntityDescription know what "whosEval" is.
Retrieve actual instance of Eval object from the mutableFetchResults and invoke whosEval on it:
if (mutableFetchResults == nil){
//handle error
} else {
[self setEvalArray:mutableFetchResults];
[self.tableView reloadData];
NSLog(#"Athlete's Full Name is: %#",_athletesFullName);
NSLog(#"This eval is for: %#", [[mutableFetchResults lastObject] whosEval]);
}
I have an NSPredicate which checks the relationship of an entity called "Eval(whosEval)" and if the relationship whosEval matches the full name of another entity, "Athlete(evals)", with the athlete that was selected, it displays all the Evals for that particular Athlete. Unfortunately, my predicate is doing weird things. If I have no athletes, and then add one, then add an eval, it shows all their evals, then I add another, the second athlete won't display any evals I added for that athlete and instead displays all of the other athlete's evals. Am I doing something incorrectly? All evals view controller is displayed prior to add Eval view controller.
allEvals.m
-(void)viewWillAppear:(BOOL)animated{
self.title = [NSString stringWithFormat:#"%#'s Evaluations",_athletesFullName];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSFetchRequest *athleteRequest = [[NSFetchRequest alloc] init];
[athleteRequest setEntity:[NSEntityDescription entityForName:#"Athlete" inManagedObjectContext:_managedObjectContext]];
NSError *athleteError = nil;
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %#", _athletesFullName];
[athleteRequest setPredicate:athletePredicate];
NSArray *results = [_managedObjectContext executeFetchRequest:athleteRequest error:&athleteError];
Athlete *currentAthlete = [results objectAtIndex:0];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosEval == %#", currentAthlete];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Eval" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"date_recorded"
ascending:NO
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil){
//handle error
}
[self setEvalArray:mutableFetchResults];
[self.tableView reloadData];
}
addEval.m
-(void)saveEval{
//insert saving attributes here
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Athlete" inManagedObjectContext:_managedObjectContext]];
NSError *error = nil;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"full == %#", _whichAthletesEval];
[request setPredicate:predicate];
NSArray *results = [_managedObjectContext executeFetchRequest:request error:&error];
Athlete *currentAthlete = [results objectAtIndex:0];
[eval setWhosEval:currentAthlete];
NSLog(#"This Eval Belongs to: %#",eval.whosEval);
NSLog(#"whichAthletesEval value is equal to: %#", _whichAthletesEval);
}
NSError *error = nil;
if(![_managedObjectContext save:&error]){
//handle dat error
}
[self.navigationController popViewControllerAnimated:YES];
}
I have left inline comments (signed off with my initials) in your viewWillAppear: method that point out what I believe to be errors. Essentially, you fetch an arbitrary athlete instead of the one that's been selected (which I'm assuming is the source of _athletesFullName. As far as your saveEval method, your naming conventions are tough to follow so it's not clear to me what further issues you could have here.
-(void)viewWillAppear:(BOOL)animated{
self.title = [NSString stringWithFormat:#"%#'s Evaluations",_athletesFullName];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSFetchRequest *athleteRequest = [[NSFetchRequest alloc] init];
[athleteRequest setEntity:[NSEntityDescription entityForName:#"Athlete" inManagedObjectContext:_managedObjectContext]];
NSError *athleteError = nil;
// No predicate is used at all for the contents of results here - see below - CV
NSArray *results = [_managedObjectContext executeFetchRequest:athleteRequest error:&athleteError];
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %#", _athletesFullName];
// This predicate never used as another predicate is set a few lines below - CV
[request setPredicate:athletePredicate];
// currentAthlete will not necessarily be the one conforming to athletePredicate
// just the first in the array of every Athlete you've fetched - CV
Athlete *currentAthlete = [results objectAtIndex:0];
// because currentAthlete is arbitrary, you're now creating a predicate you likely didn't intend to - CV
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosEval == %#", currentAthlete];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Eval" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"date_recorded"
ascending:NO
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil){
//handle error
}
[self setEvalArray:mutableFetchResults];
[self.tableView reloadData];
}
I have the following fetch. I want to fetch the Session object for which the predicate is true.
Am I doing this right? And how can I init/define indexPath, because it is not being recognized.
NSDate * searchDate = [formatter dateFromString:dateString];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Session" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:#" timeStamp == %# ", searchDate];
[request setPredicate: predicate1];
[request setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
SessionViewController *sessionViewController = [[SessionViewController alloc] initWithNibName:#"SessionViewController" bundle:nil];
self.selectedSession = (Session *)[array objectAtIndexPath:indexPath];
sessionViewController.selectedSession = self.selectedSession;
[self.navigationController pushViewController:sessionViewController animated:YES];
[sessionViewController release];
[sortDescriptor release];
[request release];
[sortDescriptors release];
Then indexPath variable is usually supplied from a tableview delegate/datasource callback. The last two lines of code you provided should be placed in one of the following methods if you are using a UITableView.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
The other lines should be in a method to get your data to display in the tableview.
-(NSArray*)sessionData
{
if(!_sessionData)
{
//FetchRequest stuff
NSError *error = nil;
_sessionData = [managedObjectContext executeFetchRequest:request error:&error];
//Error checking/logging
}
return _sessionData;
}
Now the following #" timeStamp == %# " will only work if the timestamp is that EXACT date to the millisecond. If this is what you want great, otherwise use a date range #" timeStamp >= %# AND timeStamp <= %# ".
Note: Your missing releases on several objects if you posted all of your code
requestsortDescriptorsortDescriptors