How to select particuler column in core data? - ios

When the user has Pressed Login button i want to display the particular first name in alert view when the user has entered their username and password.
Please help me.
Thanks in advance.
Help will be appreciated.
- (IBAction)LoginPressed:(id)sender
{
if (managedObjContext == nil) {
AppDelegate *app = (AppDelegate*)[UIApplication sharedApplication].delegate;
managedObjContext= app.managedObjectContext;
}
NSFetchRequest *request =[[NSFetchRequest alloc]init];
NSEntityDescription *rocordTableEntity = [NSEntityDescription entityForName:#"RecordTable" inManagedObjectContext:managedObjContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"username==% #AND password==%#",L_usernameField.text,L_passwordField.text];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"firstname=%#",[managedObjContext valueForKey:#"firstname"]];
[request setEntity:rocordTableEntity];
[request setPredicate:predicate];
[request setPredicate:pred];
NSError *error;
NSArray *arrarforCheckingUserANDPass = [managedObjContext executeFetchRequest:request error:&error];
NSString *value = [arrarforCheckingUserANDPass valueForKey:#"firstname"];
if (arrarforCheckingUserANDPass.count != 0) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Welcome" message:value d elegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
else{
NSLog(#"not matched");
}
}

Your second setPredicate overwrites the first one. You do not need it. You get the whole entity and then simply access the firstName property. Your first predicate has wrong syntax.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"RecordTable"];
request.predicate = [NSPredicate predicateWithFormat:
#"username==%# AND password==%#",L_usernameField.text,L_passwordField.text];
NSArray *result = [self.managedObjectContext executeFetchRequest:request error:nil];
RecordTable *user = result.firstObject;
if (user) {
NSLog(#"The first name is %#.", user.firstName);
}
BTW, why does your method start with a capital letter? That is a very bad habit. Your entity name is also a disaster. "RecordTable" is about the worst entity name you could choose. If it is a user, call it "User". Following convention, I camel-cased your firstName property as well.

Related

coreData existing validation

so I'm doing application form using CoreData
First I'm creating "Shop" with unique name and some properties.
In application you can edit that "Shop", and I'm trying to make validation by "shopName" to avoid a creation another "Shop" with same name.
I'm using this:
-(BOOL)uniqueEntityExistsWithEnityName {
BOOL returnValue = NO;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shop"];
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"shopName = [cd] %#", _shopName.text];
NSSortDescriptor *shop = [[NSSortDescriptor alloc] initWithKey:#"shopName" ascending:YES];
[request setSortDescriptors: #[shop]];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *matches = [self.managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"request = %#",predicate);
if (!matches) {
NSLog(#"Error: Couldn't execute fetch request %#", error);
}
else if([matches count] > 1) {
NSString *existShop = [NSString stringWithFormat:#"Could Be Only One %# Shop", _shopName.text];
UIAlertView *exist = [[UIAlertView alloc]initWithTitle:#"Shop Exists in Your Records"
message:existShop
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[exist show];
NSLog(#"Error: Have more than %lu records",
(unsigned long)[matches count]);
returnValue = YES;
}
else {
NSLog(#"%lu object in record", (unsigned long)[matches count]);
[self oldShopDelete];
[self checkShopPhoneNumber];
editShop.shopName = _shopName.text;
editShop.shopPhoneNumber = _shopPhoneNumber.text;
editShop.shopSecondPhoneNumber = _shopSecondPhoneNumber.text;
editShop.shopEmail = _shopEmail.text;
editShop.shopNote = _shopNoteView.text;
[super saveAndDissmiss];
returnValue = YES;
}
return returnValue;
}
With that code you still have opportunity to save one more edited "Shop" with same name.
But the thing is - I can not make [matches count] = 1 after this I'll no chance to edit that Shop
Maybe there are another way to do such validation?
Check for a name clash only when the Name is actually being set for the first time or edited.
You can also pass the current shop into the predicate to ensure AND SELF != %# so there will be no match with an existing shop being edited but with an unchanged name.

Core Data NSFetchrequest integer

I have the following scenario. I have an app that handles data by using Core Data. I have an entity called "Brothers" which has 3 attributes: Name, Status, Age.
lets say that I have 1 record on my database that has:
-Name ==> Joe (String)
-Status ==> Married (String)
-Age ==> 28 (Integer)
I have an UIlabel a UItextfield and a Button. I want to be able to type the name (in this case Joe) on the UItextfield press the button and display the age (in this case 28) in the UILabel. I would also like to store the age value into a variable type integer so I can make some calculations with it later on.
below the code that I have inside the button.
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"Brothers" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"age %d", [self.age.text integerValue]];
[request setPredicate:predicate];
NSError *error;
NSArray *integer = [context executeFetchRequest:request error:&error];
self.displayLabel.text = integer;
Update #1
I updated the code that i have inside the button and now i am able to search by the name and display the age. I'm still looking into storing the age as an integer into a variable so i can use it later on.
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"Brothers" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"firstname like %#", self.firstnameTextField.text];
[request setPredicate:predicate];
NSError *error;
NSArray *integer = [context executeFetchRequest:request error:&error];
if(integer.count <= 0){
self.displayLabel.text = #"No records found";
}
else {
NSString *age;
for (NSManagedObject *object in integer) {
age = [object valueForKey:#"age"];
}
self.displayLabel.text = [NSString stringWithFormat:#"age: %#",age];
}
}
A predicate is an expression. If the expression evaluates to true then the predicate is satisfied. So if you were searching by age you'd use e.g.
[NSPredicate predicateWithFormat:#"age = %d", [self.age.text integerValue]]
Or by name:
[NSPredicate predicateWithFormat:#"name = %#", someNameOrOther]
Or by both:
[NSPredicate predicateWithFormat:#"(name = %#) and (age = %d)", someNameOrOther, [self.age.text integerValue]]
A fetch request gets the actual NSManagedObjects. So you'd get back an array of Brothers. Therefore you probably want something more like this to output a name:
if([array count])
self.displayLabel.text = [array[0] name];
Or for an age:
...
self.displayLabel.text = [[array[0] age] stringValue];
Or whatever other property you're outputting.
I think your predicate is wrong, the proper format would be this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"age.integerValue == %d", [self.age.text integerValue]];

Set 2 NSPredicates on a NSFetchRequest

I'm using Core Data and have a to-many relationship with the following entities:
Athlete(evals)<-->>Eval(whosEval)
It starts with a table view that lists ALL athletes in the database. Then when you select an Athlete it pulls up their Evals in a table view. The problem is the way I am doing this is through checking their full name. Unfortunately, it is possible for 2 athletes to have the same name. For this reason, I check their parent's name as well, but I think I am doing it incorrectly. Can anyone explain why the following doesn't work and how I should do it correctly? What happens with this code is if 2 Athletes have the same name, they'll share results. Even if their Parent's Name is different.
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];
if([results count] >1){
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"pfull == %#", _athletesParentsFullName];
[athleteRequest setPredicate:athletePredicate];
}
Athlete *athleteSelected;
if([results count] >0){
Athlete *currentAthlete = [results objectAtIndex:0];
athleteSelected = currentAthlete;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosEval == %#", athleteSelected];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Eval" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
Modifying athleteRequest after the request has been executed does not have
any effect on the result. Why not simply
NSPredicate *athletePredicate = [NSPredicate predicateWithFormat:#"full == %# AND (pfull == nil OR pfull == %#)",
_athletesFullName, _athletesParentsFullName];
?
Apart from that, it would probably be better to identify the objects by some
unique identifier (e.g. a unique athlete number) instead of relying on name
and parent's name.
Your scenario is really simple, but for more complex situations, you can use compound predicates.
Read this awesome article from NSHipster for more informations:
http://nshipster.com/nspredicate/

How to update in Core Data?

I saw many questions about Core Data updates. Actually I am creating a simple application contact list app. It contains add, edit, delete and update functionalities. Here my update code. It works and updates, but it updates all the contact list. I need to update specific contacts only.
- (IBAction)updatePressed:(id)sender
{
delegate = [[AppDelegate alloc]init];
delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
name2 = emailtxt1.text;
email2 = nametext1.text;
mobile2 = numbertxt1.text;
dict = [[NSMutableDictionary alloc] init];
[dict setObject:nametext1.text forKey:#"NAME"];
[dict setObject:emailtxt1.text forKey:#"EMAIL"];
[dict setObject:numbertxt1.text forKey:#"MOBILE"];
[delegate UpdateDiary:dict];
}
- (void)UpdateDiary:(NSMutableDictionary *)dictionary
{
NSLog(#"update book Details Function Entered");
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Diary"inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *mutableFetchResult = [[[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy] autorelease];
if (mutableFetchResult == nil) {
NSLog(#"Fetch result error %#, %#", error, [error userInfo]);
}
for (Diary *ob2 in mutableFetchResult)
{
{
ob2.name = [dictionary objectForKey:#"NAME"];
ob2.email=[dictionary objectForKey:#"EMAIL"];
ob2.phone=[dictionary objectForKey:#"MOBILE"];
}
}
if(![self.managedObjectContext save:&error])
{
if([error localizedDescription] != nil)
{
NSLog(#"%#",error);
}
else
{
}
}
}
You need to set a predicate on your fetch request. That's how it knows which object(s) you want, rather than just fetching them all.
You could do something like:
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"email == %#", anEmailAddress];
If you did that, then the result of executing the fetch request would just be objects that matched the email address you set in the predicate.
Note, of course, that if there is more than one object with the same email address, then the fetch request would fetch all of them.
A better design for your app might be, when you go into the edit form, keep around the Core Data object that you're editing, possibly in a property on your view controller. (You'll have it around at that point I reckon, since you'll need to know what to populate the fields with.) That way you don't need to perform a fetch at the time the user is trying to commit the edit — you can just use the object you've kept around.
- (void)UpdateBook:(NSMutableDictionary *)dictionary
{
NSLog(#"update book Details Function Entered");
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Book"inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"bookID = %#", [dictionary objectForKey:#"vID"]];
NSArray *mutableFetchResult = [[[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy] autorelease];
if (mutableFetchResult == nil) {
NSLog(#"Fetch result error %#, %#", error, [error userInfo]);
}
for (Book *ob2 in mutableFetchResult)
{
{
ob2.name = [dictionary objectForKey:#"VName1"];
ob2.author=[dictionary objectForKey:#"VAuthor1"];
ob2.discription=[dictionary objectForKey:#"VDiscription1"];
ob2.bookID=[dictionary objectForKey:#"vID"];
}
}
if(![self.managedObjectContext save:&error])
{
if([error localizedDescription] != nil)
{
NSLog(#"%#",error);
}
else
{
}
}
}

NSPredicate Returns No Results with Fetch Request, Works with Array Filtering

My situation is simple: I have some records in my core data store. One of their attributes is a string called "localId". There's a point where I'd like to find the record with a particular localId value. The obvious way to do this is with an NSFetchRequest and an NSPredicate. However, when I set this up, the request returns zero records.
If, however, I use the fetch request without the predicate, returning all records, and just loop over them looking for the target localId value, I do find the record I'm looking for. In other words, the record is there, but the fetch request can't find it.
My other methods in which I use fetch requests and predicates are all working as expected. I don't know why this one is failing.
I want to do this:
- (void)deleteResultWithLocalID:(NSString *)localId {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"WCAAssessmentResult" inManagedObjectContext:context]];
[request setPredicate:[NSPredicate predicateWithFormat:#"localId == %#", localId]];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
NSAssert(error == nil, ([NSString stringWithFormat:#"Error: %#", error]));
if ([results count]) [context deleteObject:[results objectAtIndex:0]];
else NSLog(#"could not find record with localID %#", localId);
[self saveContext];
}
But I end up having to do this:
- (void)deleteResultWithLocalID:(NSString *)localId {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"WCAAssessmentResult" inManagedObjectContext:context]];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
NSAssert(error == nil, ([NSString stringWithFormat:#"Error: %#", error]));
for (WCAAssessmentResult *result in results) {
if ([result.localId isEqualToString:localId]) {
NSLog(#"result found, deleted");
[context deleteObject:result];
}
}
[self saveContext];
}
Any clues as to what could be going wrong?
edit
I've found that I can use the predicate I'm creating to get the results I expect after the fetch request has been executed. So, the following also works:
- (WCAChecklistItem *)checklistItemWithId:(NSNumber *)itemId {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"WCAChecklistItem" inManagedObjectContext:context]];
NSArray *foundRecords = [context executeFetchRequest:request error:nil];
foundRecords = [foundRecords filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"serverId == %#", itemId]];
if ([foundRecords count]) {
return [foundRecords objectAtIndex:0];
} else {
NSLog(#"can't find checklist item with id %#", itemId);
return nil;
}
}
UPDATE
I've come across someone else experiencing this very issue:
http://markmail.org/message/7zbcxlaqcgtttqo4
He hasn't found a solution either.
Blimey! I'm stumped.
Thanks!
If localId is a numerical value, then you should use an NSNumber object in the predicate formation instead of an NSString.
[request setPredicate:[NSPredicate predicateWithFormat:#"localId == %#",
[NSNumber numberWithString:localId]]];
NSPredicate format strings automatically quote NSString objects.
Hate to say it but the most common cause of these types of problems is simple typos. Make sure that your attribute names and the predicate are the same. Make sure that your property names and the attributes names are the same. If a reference to a property works but a reference to attribute name doesn't there is probably a mismatch.
You could test for the latter by comparing the return of:
[result valueForKey:#"localID"]
... with the return of:
result.localID

Resources