Reputation: 981
I have a data model with an entity of HYUser
and the attributes of firstName
, lastName
, email
, gender
and phone
. When I check my .sqlite
DB, nothing is there. I have attached my entire button action that should save my object.
- (IBAction)btnUserDataSave:(id)sender {
NSEntityDescription * entityDescription = [NSEntityDescription entityForName:@"HYUser" inManagedObjectContext:context];
NSManagedObject *newUser = [[NSManagedObject alloc]initWithEntity:entityDescription insertIntoManagedObjectContext:context];
NSString *gender = NULL;
NSError *error = nil;
[newUser setValue:self.txtfFirstName.text forKey:@"firstName"];
[newUser setValue:self.txtfLastName.text forKey:@"lastName"];
[newUser setValue:self.txtfPhoneNumber.text forKey:@"phone"];
[newUser setValue:self.txtfUserEmail.text forKey:@"email"];
if (self.segmentControlGender.selectedSegmentIndex == 0) {
gender = @"Male";
}else if(self.segmentControlGender.selectedSegmentIndex == 1){
gender = @"Female";
}else{
NSLog(@"ERROR in gender saving");
}
[newUser setValue:gender forKey:@"gender"];
if ([self.txtfFirstName.text isEqual: @""] || [self.txtfLastName.text isEqual: @""] || [self.txtfPhoneNumber.text isEqual: @""] || [self.txtfUserEmail.text isEqual: @""]) {
UIAlertController* errorPrompt = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Required Fields", @"Required Fields")
message:NSLocalizedString(@"All fields are required to complete Sign-up. ", nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK",nil)
style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
}];
[errorPrompt addAction:okAction];
[self presentViewController:errorPrompt animated:YES completion:NULL];
}else{
if(![context save:&error]) {
self.labelStatus.text = @"Error";
NSLog(@"%@, %@", error, error.localizedDescription);
}else{
[context save:&error];
self.labelStatus.text = @"Saved";
}
}
}
Upvotes: 1
Views: 96
Reputation: 981
I solved the issue, looks like it had something to do with the way I was trying to save the objects. Below is my entire code for signing up a new user.
- (IBAction)btnUserDataSave:(id)sender {
HYUser* signUpUserObject = [NSEntityDescription insertNewObjectForEntityForName:@"HYUser" inManagedObjectContext:context];
NSString *gender = nil;
NSError *error = nil;
if ([self.txtfFirstName.text isEqual: @""] || [self.txtfLastName.text isEqual: @""] || [self.txtfPhoneNumber.text isEqual: @""] || [self.txtfUserEmail.text isEqual: @""]) {
UIAlertController* errorPrompt = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Required Fields", @"Required Fields")
message:NSLocalizedString(@"All fields are required to complete Sign-up. ", nil)
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK",nil)
style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
}];
[errorPrompt addAction:okAction];
[self presentViewController:errorPrompt animated:YES completion:NULL];
}
else {
self.labelStatus.text = @"Saved";
[signUpUserObject setValue:self.txtfFirstName.text forKey:@"firstName"];
[signUpUserObject setValue:self.txtfLastName.text forKey:@"lastName"];
[signUpUserObject setValue:self.txtfPhoneNumber.text forKey:@"phone"];
[signUpUserObject setValue:self.txtfUserEmail.text forKey:@"email"];
gender = self.segmentControlGender.selectedSegmentIndex == 0 ? @"Male" : @"Female";
[signUpUserObject setValue:gender forKey:@"gender"];
if(![context save:&error]) {
self.labelStatus.text = @"Error";
NSLog(@"%@, %@", error, error.localizedDescription);
}
else {
UIAlertController* errorPrompt = [UIAlertController alertControllerWithTitle:@"HairYourWay"
message:NSLocalizedString(@"STR_NEW_USER_SIGN_UP_SUCCEEDED", @"Success")
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK",nil)
style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self.navigationController popViewControllerAnimated:YES];
}];
[errorPrompt addAction:okAction];
[self presentViewController:errorPrompt animated:YES completion:NULL];
}
}
}
Upvotes: 0
Reputation: 3791
In addition to Hal Mueller's list of things to check, I'd add...
If I'm going to check against isEqual: @""
in most cases I also check against isEqual: nil
...
Using your example...
if ([self.txtfFirstName.text isEqual: @""] ||
[self.txtfFirstName.text isEqual: nil] ||
[self.txtfLastName.text isEqual: @""] ||
[self.txtfLastName.text isEqual: nil] ||
[self.txtfPhoneNumber.text isEqual: @""] ||
[self.txtfPhoneNumber.text isEqual: nil] ||
[self.txtfUserEmail.text isEqual: @""] ||
[self.txtfUserEmail.text isEqual: nil]) {
Upvotes: 0
Reputation: 7646
Things to check:
Is context
nil, or does it really point to an NSManagedObjectContext
? How was it created? Does it have a persistent store coordinator?
Are any of the intermediate objects nil? A typo in the entityForName:
argument will cause the insertion to fail silently. Perhaps add NSParamterAssert(newUser)
. If that blows up, you know to backtrack and figure out why.
Also...
Your use of literal keystrings in code is begging for a silent runtime error. A typo won't be caught by the compiler. Define the strings symbolically. Better yet, make your own custom NSManagedObject subclass and you can use regular setters/getters instead of valueForKey:
.
You're calling -save:
a second time on the context if the first call failed. That's not likely to help. Consider putting the error.localizedDescription
into your labelStatus.text
instead of the word "Error".
I'd probably test to see if the length of the text in the various fields was greater than 0, instead of comparing against @""
. It's shorter, and easier to read. See also https://www.bignerdranch.com/blog/isequal-vs-isequaltostring/ for a couple of reasons to prefer isEqualToString:
.
Upvotes: 0
Reputation: 1341
Try to fetch the object back from core data just to be sure it didn't make it in.
Instead of initWithEntity, you could try this.
[NSEntityDescription insertNewObjectForEntityForName:@"HYUser" inManagedObjectContext:context];
You are saving the context twice, 2nd time is if the first time was successful. That won't cause an issue, but isn't needed.
Also, if the user fails your field validation, you've already created the object in the context. Is that desired or should the validation occur before the managed object is created?
Upvotes: 0