Getting username after authentification with coredata predicate - ios

I am a beginner in Xcode. I would like to get the username or the ID after the user enters their login and password in textfield. I am sure I am doing wrong.
My code bug is after the access granted.
app due to uncaught exception
'`NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]:
object cannot be nil`'
Here is my code:
- (IBAction)stepInButton:(id)sender {
AppDelegate *appDelegateCoreData = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegateCoreData managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Player" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred = [NSPredicate predicateWithFormat:
#"(playerlogin = %#) AND (playerpassword =%#)", self.loginTextField.text, self.passwordTextField.text];
[request setPredicate:pred];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
self.loginStatusLabel.hidden = NO;
NSLog(#"LOGIN IN ACCESS DENIED");
} else {
NSLog(#"LOGIN IN ACCESS GRANTED");
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:#"playerfirstname"];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setExpression:keyPathExpression];
[expressionDescription setExpressionResultType:NSDateAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
// Handle the error.
}
else {
if ([objects count] > 0) {
NSString *playerFirstName = [[objects objectAtIndex:0] valueForKey:#"playerfirstname"];
NSLog(#"PlayerFirstName: %#", [[objects objectAtIndex:0] valueForKey:#"playerfirstname"]);
self.welcomePlayerLabel.text = [NSString stringWithFormat: #"Welcome %#", playerFirstName];
}
}
self.loginStatusLabel.hidden = YES;
self.signButton.hidden = YES;
self.stepButton.hidden =YES;
self.loginStatusLabel.text =(#"Access Granted");
self.loginStatusLabel.textColor = [UIColor greenColor];
self.loginStatusLabel.hidden = NO;
//FirstViewController *firstViewController = [[FirstViewController alloc] init];
//[self.navigationController pushViewController:firstViewController animated:YES];
//[self.navigationController pushViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"first"] animated:YES];
}
}

ok I got it.
I retieved the playerFirstName directly form object like Dan Shelly said. Thanks you Dan.
- (IBAction)stepInButton:(id)sender {
AppDelegate *appDelegateCoreData = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegateCoreData managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Player" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred = [NSPredicate predicateWithFormat:
#"(playerlogin = %#) AND (playerpassword =%#)", self.loginTextField.text, self.passwordTextField.text];
[request setPredicate:pred];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
self.loginStatusLabel.hidden = NO;
NSLog(#"LOGIN IN ACCESS DENIED");
} else {
NSLog(#"LOGIN IN ACCESS GRANTED");
NSString *playerFirstName = [[objects objectAtIndex:0] valueForKey:#"playerfirstname"];
self.welcomePlayerLabel.text = [NSString stringWithFormat: #"Welcome %#", playerFirstName];
self.loginStatusLabel.hidden = YES;
self.signButton.hidden = YES;
self.stepButton.hidden =YES;
self.loginStatusLabel.text =(#"Access Granted");
self.loginStatusLabel.textColor = [UIColor greenColor];
self.loginStatusLabel.hidden = NO;
}
}

Related

I cannot insert value with NSNumber datatype into my coredata

Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: 'Unacceptable type of value for
attribute: property = "XXXXX"; desired type = NSNumber; given type =
NSTaggedPointerString; value = 0.'
Tried: [enter image description here][1]
[message setValue:localID forKey:#"local_id"];
localID is of type NSNumber
DataModel image: [1]: https://i.stack.imgur.com/7WTlU.png
[self insertInLocatDB:print_data entityName:#"Message_data" withPredicate:#"receiver_id" filterWith:#"unique_id"];
Using this to insert into CoreData:
-(void)insertInLocatDB :(NSMutableArray *)arr_msg entityName:(NSString*)name withPredicate:(NSString*)predicateText filterWith:(NSString*)filterText
{
NSEntityDescription *entitydesc=[NSEntityDescription entityForName:name inManagedObjectContext:app.context];
NSFetchRequest *request=[[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSInteger local_id =[self getMaxLocalId:name];
for(int i=0; i<[arr_msg count]; i++)
{
[fetched_data removeAllObjects];
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"%# like %# ",predicateText,[[arr_msg objectAtIndex:i]objectForKey:predicateText]];
[request setPredicate:predicate];
NSError *error;
NSArray *matchingData=[app.context executeFetchRequest:request error:&error];
local_id=local_id+1;
for (NSManagedObject *obj in matchingData)
{
[fetched_data addObject:[obj valueForKey:filterText]];
}
NSString *filter=[[arr_msg objectAtIndex:i] objectForKey:filterText];
if(![fetched_data containsObject:filter])
{
NSManagedObject *message=[[NSManagedObject alloc] initWithEntity:entitydesc insertIntoManagedObjectContext:app.context];
[arr_keys setArray:[[arr_msg objectAtIndex:i] allKeys]];
[arr_values setArray:[[arr_msg objectAtIndex:i] allValues]];
[message setValue:[NSNumber numberWithInteger:local_id] forKey:#"local_id"];
for (int i=0;i<[arr_keys count];i++)
{
if( [[message.entity propertiesByName] objectForKey:[arr_keys objectAtIndex:i]] != nil
&& ([[[message.entity propertiesByName] objectForKey:[arr_keys objectAtIndex:i]] isKindOfClass:[NSAttributeDescription class]]) )
{
[message setValue:[arr_values objectAtIndex:i] forKey:[arr_keys objectAtIndex:i]];
}
}
[arr_keys removeAllObjects];
[arr_values removeAllObjects];
}
}
}
If you have a core data attribute as shown in my screen shot.
Then, the following snippet of code will work for you.
BOOL result;
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *newMessage = [NSEntityDescription insertNewObjectForEntityForName:#"message"
inManagedObjectContext:context];
[newMessage setValue:[NSNumber numberWithInt:local_id] forKey:#"local_id"];
[newMovie setValue:movieName forKey:#"message"];
NSError *error = nil;
// Save the object to persistent store
result = YES;
if (![context save:&error]) {
result = NO;
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
return result;
and a function to get the managed object context
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
Edited Code of Sandhya.
-(NSInteger)getMaxLocalId :(NSString*)entitiyName
{
NSEntityDescription *entitydesc=[NSEntityDescription entityForName:entitiyName inManagedObjectContext:app.context];
NSFetchRequest *request=[[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSInteger local_id = 0;
request.fetchLimit = 1;
request.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"local_id" ascending:NO]];
NSError *error = nil;
local_id=[[app.context executeFetchRequest:request error:&error].firstObject integerValue];
return local_id;
}
Then used the following to insert in to CoreData
NSInteger local_id =[self getMaxLocalId:name];
local_id=local_id+1;
[message setValue:[NSNumber numberWithInteger:local_id] forKey:#"local_id"];
make sure you get the local_id.
As you have NSInteger, For conversion you should use [NSNumber numberWithInteger:] Instead of [NSNumber numberWithInt:]
UPDATE 2 :
NSString *filter=[[arr_msg objectAtIndex:i] objectForKey:filterText];
if(![fetched_data containsObject:filter])
{
NSManagedObject *message=[[NSManagedObject alloc] initWithEntity:entitydesc insertIntoManagedObjectContext:app.context];
[arr_keys setArray:[[arr_msg objectAtIndex:i] allKeys]];
[arr_values setArray:[[arr_msg objectAtIndex:i] allValues]];
[message setValue:[NSNumber numberWithInteger:local_id] forKey:#"local_id"];
for (int i=0;i<[arr_keys count];i++)
{
if( [[message.entity propertiesByName] objectForKey:[arr_keys objectAtIndex:i]] != nil
&& ([[[message.entity propertiesByName] objectForKey:[arr_keys objectAtIndex:i]] isKindOfClass:[NSAttributeDescription class]]) )
{
if(![[arr_keys objectAtIndex:i] isEqualToString:#"local_id"]){
[message setValue:[arr_values objectAtIndex:i] forKey:[arr_keys objectAtIndex:i]];
}
}
}
[arr_keys removeAllObjects];
[arr_values removeAllObjects];
}
-(NSInteger)getMaxLocalId :(NSString*)entitiyName
{
NSEntityDescription *entitydesc=[NSEntityDescription entityForName:entitiyName inManagedObjectContext:app.context];
NSFetchRequest *request=[[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSInteger local_id = 0;
request.fetchLimit = 1;
request.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"local_id" ascending:NO]];
NSError *error = nil;
local_id=[[app.context executeFetchRequest:request error:&error].firstObject integerValue];
return local_id;
}
Then used the following to insert in to CoreData
NSInteger local_id =[self getMaxLocalId:name];
local_id=local_id+1;
[message setValue:myNumber forKey:#"local_id"];

Issue with Coredata update

I'm trying to update certain currency abbreviations in the coredata with this function.
- (void)updateCurrencies
{
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Transaction" inManagedObjectContext:managedObjectContext]];
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"Number of data : %lu", (unsigned long)[results count]);
for (int i = 0; i < [results count]; i++) {
Transaction* t = [results objectAtIndex:0];
NSLog(#"currency: %#", t.currency);
if ([t.currency isEqualToString:#"CAN"]) {
t.currency = #"CAD";
NSLog(#"new currency set.");
}
[self saveContext];
}
}
}
I call this function in didFinishLaunchingWithOptions. Now, the log does inform me that t.currency has been updated to CAD. However when I retrieve the data again in HomeViewController and log the currency, it is back to CAN. This is the code in HomeViewController,
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *transaction = [NSEntityDescription entityForName:#"Transaction" inManagedObjectContext:_managedObjectContext];
[request setEntity:transaction];
request.predicate = [NSPredicate predicateWithFormat:#"transactionToUser = %#", [self.content objectAtIndex:i]];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"postdate" ascending:NO];
NSArray *descriptors = [[NSArray alloc] initWithObjects:descriptor, nil];
[request setSortDescriptors:descriptors];
NSError *error = nil;
NSMutableArray *mutableResult = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableResult == nil) {
//handle error
}
for (int k = 0; k < [mutableResult count]; k++) {
Transaction *t = [mutableResult objectAtIndex:k];
NSLog(#"currency xx: %#", t.currency);
}
What am I doing wrong? Any help is appreciated. Thanks.
Fixed it with a different for loop.
for (Transaction *t in results)
{
...
}

Warning: Attempt to present View Controller on whose view is not in the hierarchy

Trying to present a new view controller as in below code, but I get the warning
"Attempt to present on whose view is not in the window hierarchy"
Warning: Attempt to present <ActivityViewController: 0x7fb6225ca8a0> on <ViewController: 0x7fb62254cb50> whose view is not in the window hierarchy!
-(IBAction) loginUser:(id)sender {
NSString *userEmail = _emailTxt.text;
NSString *userPassword = _password.text;
ActivityViewController *activities = [[ActivityViewController alloc] init];
NSManagedObjectContext *moc = [DataAccessLayer context];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"SignupInfo" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
request.predicate = [NSPredicate predicateWithFormat:#"email == %#", userEmail];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"email" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *result = [moc executeFetchRequest:request error:&error];
if(result.count > 0) {
NSManagedObject *fetchedsignupInfo = (NSManagedObject *)[result objectAtIndex:0];
NSString *storedUserEmail = [fetchedsignupInfo valueForKey:#"email"];
NSString *storedPassword = [fetchedsignupInfo valueForKey:#"password"];
if(([userEmail length] == 0) || ([userPassword length] == 0))
{
// Error to enter Email or Password
[self displayAlertMessage:#"Email or Password are required"];
} else if (![userEmail isEqualToString:storedUserEmail] || ![userPassword isEqualToString:storedPassword]) {
// Error - Wrong email or password entered
[self displayAlertMessage:#"Wrong email or password entered"];
} else if ( [userEmail isEqualToString:storedUserEmail] && [userPassword isEqualToString:storedPassword]) {
// Login Successful
//[self.navigationController presentViewController:activities animated:YES];
[self presentViewController:activities animated:YES completion:nil];
}
}
}

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

Weird NSPredicate Behavior?

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

Resources