Weird NSPredicate Behavior? - ios

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];
}

Related

Transformable attribute on iOS

I have stored dictionary in the transformable attribute.I want to know
How to get single data from it?**
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]
initWithEntityName:#"MemberProfile"];
NSSortDescriptor *ordering = [[NSSortDescriptor alloc] initWithKey:
[member.member_Profile objectForKey:"#order"] ascending:YES];
[fetchRequest setSortDescriptors:[NSArray
arrayWithObjects:ordering,nil]];
NSArray *result = [self.managedObjectContext
executeFetchRequest:fetchRequest error:Nil];
self.masterList = [[NSMutableArray alloc] initWithArray:result];
Import NSManagedObject(InstallProject) and fetch one object like this,
-(InstallProject *)readSelectedInstall:(NSString *)projIDString
{
NSArray *fetchedObjects;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"InstallProject" inManagedObjectContext: context];
[fetch setEntity:entityDescription];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"(ANY ProjID contains[cd] %#)",projIDString]];
NSError * error = nil;
fetchedObjects = [context executeFetchRequest:fetch error:&error];
if([fetchedObjects count] == 1)
return [fetchedObjects objectAtIndex:0];
else
return nil;
}

How to get chat history of a selected user in XMPP

I am new to xmpp , i need to store and show the chat history of users . i am getting the full history while using the below code.I only need the chat history of the selected user.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
XMPPMessageArchivingCoreDataStorage *xmppMessageArchivingCoreDataStorage=[XMPPMessageArchivingCoreDataStorage sharedInstance];
NSManagedObjectContext *context = [xmppMessageArchivingCoreDataStorage mainThreadManagedObjectContext];
NSEntityDescription *messageEntity = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context];
fetchRequest.entity = messageEntity;
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"timestamp" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
[self print:[[NSMutableArray alloc]initWithArray:results]];
How can i get the chat history of a particular user,. i have searched a lot but couldnt got a success
Try this
- (void)loadChatHistoryWithUserName:(NSString *)userName
{
NSString *userJid = [NSString stringWithFormat:#"%##%#",userName,self.hostName];
NSManagedObjectContext *moc = [_xmppMsgStorage mainThreadManagedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entityDescription];
NSError *error;
NSString *predicateFrmt = #"bareJidStr == %#";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, userJid];
request.predicate = predicate;
NSArray *messages = [moc executeFetchRequest:request error:&error];
}

XMPP, CoreData - how to load only self and destination user messages?

I save to core data and load all messages with code below, but how can I load only messages for 2 users, for self user and for destination user, I want base it on user JID.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [[self appDelegate].xmppMessageArchivingCoreDataStorage mainThreadManagedObjectContext];
NSEntityDescription *messageEntity = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context];
fetchRequest.entity = messageEntity;
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"timestamp" ascending:YES];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
//Now you get the NSArray with element type of "XMPPMessageArchiving_Message_CoreDataObject"
assuming your message objects have a from relationshit to a User entity.
As simple as adding (before executing the request):
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"from = %# OR from = %#",selfUser,otherUser];
Where selfUser and otherUser are User core data managed objects or managed object IDs of users.
if you use a field identifier (highly not recomended):
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"bareJID.bare = %# OR bareJID.bare = %#",selfUser.jid,otherUser.jid];
You might want to read THIS
I have used following method and it worked correctly :)
-(void)checkForPastMessageAndDisplayIt
{
NSString *strmyid = #"user1#domain";
NSString *strBuddy = #"user2#domain";
NSManagedObjectContext *moc = [[self appDelegate] managedObjectContext_message_achiving];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"bareJidStr = %# OR bareJidStr = %#", strmyid, strBuddy];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *messagesArray = [moc executeFetchRequest:fetchRequest error:&error];
[messagesArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id messageObject = [messagesArray objectAtIndex:idx];
if ([messageObject isKindOfClass:[XMPPMessageArchiving_Message_CoreDataObject class]]) {
XMPPMessageArchiving_Message_CoreDataObject *currentMessageCoreDataObject = (XMPPMessageArchiving_Message_CoreDataObject*)messageObject;
XMPPMessage *message = currentMessageCoreDataObject.message;
if (message!=nil) {
[messages addObject:message];
}
}
}];
}
You can use like that
-(void)testMessageArchiving {
NSString *strmyid = #"myid";
NSString *strBuddy ="toid";
NSLog(#"my id and buddy is is %# and %#",strmyid,strBuddy);
XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
request.predicate = [NSPredicate predicateWithFormat:#"bareJidStr = %# OR bareJidStr = %#", strmyid, strBuddy];
NSError *error;
NSArray *messages = [moc executeFetchRequest:request error:&error];
// NSLog(#"the history of messages is %#",messages);
[self print:[[NSMutableArray alloc]initWithArray:messages]];

How do we Retrive Data Which is Saved By Using Core Data in iOS

I am New to Core Data.I have Developed an application. In my application i am having Registration, Login, Forgot password Forms.
In Registration Form i Write this code for registration.
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"User" inManagedObjectContext:context];
NSManagedObject *newuser = [[NSManagedObject alloc]initWithEntity:entitydesc insertIntoManagedObjectContext:context];
[newuser setValue:self.registerUsername.text forKey:#"username"];
[newuser setValue:self.registerPassword.text forKey:#"password"];
[newuser setValue:self.registerConfirmPassword.text forKey:#"confirmpassword"];
[newuser setValue:self.registerMobileNumber.text forKey:#"mobilenumber"];
NSError *error;
[context save:&error];
In Login Form i write this Code:
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"User" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username like %# and password like %#",self.logUsername.text,self.logPassword.text];
[request setPredicate:predicate];
NSError *error;
NSArray *matchingData = [context executeFetchRequest:request error:&error];
if(matchingData.count<=0)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error!" message:#"Username and password does not match" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
else
{
NSString *username;
NSString *password;
for(NSManagedObject *obj in matchingData)
{
username = [obj valueForKey:#"username"];
password = [obj valueForKey:#"password"];
}
SecurityHome *securityhome = [[SecurityHome alloc]init];
[self.navigationController pushViewController:securityhome animated:YES];
}
}
Both were Working fine. Now i want to Display Password in Forgot password page if the user entered Username and Mobile number Correctly.How Can i Achieve this?
Set example predicate and sort orderings...
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(lastName LIKE[c] 'Worsley') AND (salary > %#)", minimumSalary];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"firstName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
You should have done some 'googling' before asking this question. Any how,Let me do it for you. Here you go.
Core Data NSFetchResult guide for developer
Ray wenderlich- Really nice tutorial
In both of the listed links, I am trying to suggest NSFetchResultControllers, as they are fast & easy. Here you can see the difference
Without NSFetchResultController,
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:#"Employee" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(lastName LIKE[c] 'Worsley') AND (salary > %#)", minimumSalary];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"firstName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
With NSFetchresultController
[[self managedObjectContext] fetchObjectsForEntityName:#"Employee" withPredicate:
#"(lastName LIKE[c] 'Worsley') AND (salary > %#)", minimumSalary];
These examples are for Famous employee table. Translate the code as per your requirement. If you are unable to work around with this code for any reason, let me know..
You can use this code for fetching details and pass the object to Forgot class and show there.
-(User*)getUserCredentialDetails:(NSUInteger)mobilenumber
{
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"mobilenumber = %d",mobileNumber];
[request setPredicate:predicate];
NSArray * resultArray = [managedObjectContext executeFetchRequest:request error:&error];
[request release];
if (error != nil)
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return [resultArray lastObject];
}

NSPredicate won't work?

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]);
}

Resources