Storing in CoreData from Array of Dictionary objects - ios

I have an array friendsArray of dictionary objects which looks something like this:
(
{
name = "james p";
phone = 345345345;
},
{
name = "sam b";
phone = 345345345;
},
{
name = "aaron s";
phone = 346346456;
}
)
Now I'm storing it to coredata like this
NSMutableDictionary *friends = [[NSMutableDictionary alloc] init];
for (int count = 0; count <[friendsArray count]; count++) {
NSError *error;
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"FriendContacts" inManagedObjectContext:context];
NSManagedObject *friendsObject = [[NSManagedObject alloc] initWithEntity:entityDesc insertIntoManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
friends = [friendsArray objectAtIndex:count];
[friendsObject setValue:[friends objectForKey:#"name"] forKey:#"name"];
[friendsObject setValue:[friends objectForKey:#"phone"] forKey:#"phone"];
[context save:&error];
}
Here is the screenshot of SQL Browser
It is storing data but making duplicate of this dictionary, I don't know why.

Try the following - its a bit cleaner :)
Observe how many times the log statement is outputted and check the object it outputs.
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"FriendContacts" inManagedObjectContext:context];
for (NSDictionary *friend in friendsArray) {
NSManagedObject *friendsObject = [[NSManagedObject alloc] initWithEntity:entityDesc insertIntoManagedObjectContext:context];
[friendsObject setValue:[friend objectForKey:#"name"] forKey:#"name"];
[friendsObject setValue:[friend objectForKey:#"phone"] forKey:#"phone"];
NSLog(#"Created new friends object: %#", friendsObject);
if ([context hasChanges]) {
NSError *error;
if (![context save:&error]) {
NSLog(#"Problem saving changes: %#", error);
}
}
}
EDIT:
You might also be better off saving after the loop is finished too (if you have a large data set), just move the if statement outside the loop.

Related

Update Core Data with JSON Key Value ( id )

I am having a problem with updating the core data.
i am downloading the data in the background thread comparing with the identifier in core data and count but am having trouble to update now i want to check the identifier present in Core data with JSON Response and if id is present in the JSON Response leave it and if not present in JSON Response (That means That record has been removed in Server side)
Here in this code am checking id is present in core data or not and now i want to check the id is present in json or not to update the records
Any help will be great appreciate thanks in advance
please check the code how am storing the data in to core data
for (int i = 0; i < [arrayData count]; i++) {
NSNumber * idNum = [arrayData objectAtIndex:i][#"id"];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Deal"];
[request setPredicate:[NSPredicate predicateWithFormat:#"identifier == %#",idNum]];
[request setFetchLimit:1];
NSUInteger count = [_managedObjectContext countForFetchRequest:request error:&error];
if (count == NSNotFound) {
NSLog(#"ERROR");
}else if (count == 0) {
Deal * dealsEntity = [NSEntityDescription insertNewObjectForEntityForName:#"Deal" inManagedObjectContext:_managedObjectContext];
NSString * name = [arrayData objectAtIndex:i][#"name"];
dealsEntity.nameAttribute = name;
dealsEntity.identifier = idNum;
[appDelegate saveContext];
}
[self performSelectorOnMainThread:#selector(updateData:) withObject:_myArray waitUntilDone:YES];
}
- (void) updateData:(NSArray *)yourData {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Deal" inManagedObjectContext:_managedObjectContext];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setEntity:entity];
NSError *error;
yourData = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
self.myArray = yourData;
[listTableView reloadData];
}
I have tried this with updating or deleting the records from coredata
for (int d = 0; d < [_myArray count]; d++) {
Deal * deal = (Deal*)_myArray[d];
NSNumber * identifier = [deal identifier];
if ([identifier isEqualToNumber:[[arrayData objectAtIndex:d] valueForKey:#"id"]] ) {
NSLog(#"equal %d",d);
} else {
NSLog(#"Kill it ");
}
}
but here the problem is Coredata has 115 records when checking with json but json will have only 114 records and it returns crash
As you have the identifier into your database you just need to change your code little bit
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Deal" inManagedObjectContext:moc]];
[request setPredicate:[NSPredicate predicateWithFormat:#"identifier == %#",idNum]];
[request setFetchLimit:1];
NSError *error = nil;
NSArray *results = [moc executeFetchRequest:request error:&error];
// check the count
if([results count] == 1) {
// Update your coredata object
} else {
// Create new object
}

iOS Core data: Fetching more objects than saved

I am new to Core Data, and I am trying to use it for saving users. However, when I first create a user it inserts the user. This seems to go fine. It is only called once.
-(void)insertUser: (User *) user{
[self userToModel:user];
NSError *error = nil;
if(![context save:&error]){
NSLog(#"Unable to save managed object context");
}
}
-(UserModel *)userToModel:(User *) user{
UserModel *usermodel = [NSEntityDescription
insertNewObjectForEntityForName:#"UserModel"
inManagedObjectContext:context];
[usermodel setValue:user.username forKey:#"username"];
[usermodel setValue:user.password forKey:#"password"];
[usermodel setValue:user.sessionid forKey:#"sessionid"];
[usermodel setValue:[NSNumber numberWithBool:TRUE] forKey:#"selected"];
[usermodel setValue:[NSNumber numberWithBool:user.beta] forKey:#"beta"];
return usermodel;
}
Next, I am fetching the users and it is returning 3 users: 2 exact similar Users, and one nil model.
-(NSMutableArray *)getUsers{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"UserModel"
inManagedObjectContext:context];
NSError *error;
[fetchRequest setEntity:entity];
NSArray *usermodels= [context executeFetchRequest:fetchRequest error:&error];
NSMutableArray *users = [[NSMutableArray alloc] init];
for(UserModel *userModel in usermodels){
User *user = [self userModelToUser:userModel];
[users addObject:user];
}
return users;
}
UserModelToUser:
-(User *)userModelToUser:(UserModel *)usermodel{
User *user = [[User alloc]initWithUsername:usermodel.username
Password:usermodel.password
CSRFToken:usermodel.csrftoken
sessionid:usermodel.sessionid
Beta:[usermodel.beta boolValue]
Selected:[usermodel.selected boolValue]];
return user;
}
SelectUser
-(void)selectUser: (User *)userToSelect OldUser:(User *)oldSelectedUser{
UserModel *oldSelectedUserModel = [self userToModel:oldSelectedUser];
UserModel *newSelectedUsermodel = [self userToModel:userToSelect];
[oldSelectedUserModel setValue:[NSNumber numberWithBool:FALSE] forKey:#"selected"];
[newSelectedUsermodel setValue:[NSNumber numberWithBool:TRUE] forKey:#"selected"];
NSError *saveError;
if (![context save:&saveError]) {
NSLog(#"Changing users failed %#", saveError);
}
}
I already tried to reinstall the app to make sure no old users are still saved or anything. Can anyone help me?

objective-c pointer to 'int *' error when assigning data across relationships

In this tutorial http://www.raywenderlich.com/934/core-data-tutorial-for-ios-getting-started, the author creates two classes FailedBankInfo and FailedBankDetails from two core data entities, which have a relationship between them, and when he assigns the object failedBankDetails to the name of the relationship details on the failedBankInfo object/pointer like this
failedBankInfo.details = failedBankDetails;
it generates this error
implicit conversion of an objective-c pointer to 'int *' is disallowed with arc
and the same error is generated when he assigns info.details to the pointer FailedBankDetails * details
for (FailedBankInfo *info in fetchedObjects) {
NSLog(#"Name: %#", info.name);
FailedBankDetails *details = info.details;
NSLog(#"Zip: %#", details.zip);
}
Can you explain why this is happening?
This is the full code that he instructs reader to insert into applicationDidFinishLaunching
NSManagedObjectContext *context = [self managedObjectContext];
FailedBankInfo *failedBankInfo = [NSEntityDescription
insertNewObjectForEntityForName:#"FailedBankInfo"
inManagedObjectContext:context];
failedBankInfo.name = #"Test Bank";
failedBankInfo.city = #"Testville";
failedBankInfo.state = #"Testland";
FailedBankDetails *failedBankDetails = [NSEntityDescription insertNewObjectForEntityForName:#"FailedBankDetails"
inManagedObjectContext:context];
failedBankDetails.closeDate = [NSDate date];
failedBankDetails.updateDate = [NSDate date];
failedBankDetails.zip = [NSNumber numberWithInt:12345];
failedBankDetails.info = failedBankInfo;
failedBankInfo.details = failedBankDetails;
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
// Test listing all FailedBankInfos from the store
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"FailedBankInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (FailedBankInfo *info in fetchedObjects) {
NSLog(#"Name: %#", info.name);
FailedBankDetails *details = info.details;
NSLog(#"Zip: %#", details.zip);
}
Before generating classes for the entities, he performed the same task/test just using the managedObject and there was no problem
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *failedBankInfo = [NSEntityDescription
insertNewObjectForEntityForName:#"FailedBankInfo"
inManagedObjectContext:context];
[failedBankInfo setValue:#"Test Bank" forKey:#"name"];
[failedBankInfo setValue:#"Testville" forKey:#"city"];
[failedBankInfo setValue:#"Testland" forKey:#"state"];
NSManagedObject *failedBankDetails = [NSEntityDescription
insertNewObjectForEntityForName:#"FailedBankDetails"
inManagedObjectContext:context];
[failedBankDetails setValue:[NSDate date] forKey:#"closeDate"];
[failedBankDetails setValue:[NSDate date] forKey:#"updateDate"];
[failedBankDetails setValue:[NSNumber numberWithInt:12345] forKey:#"zip"];
[failedBankDetails setValue:failedBankInfo forKey:#"info"];
[failedBankInfo setValue:failedBankDetails forKey:#"details"];
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"FailedBankInfo" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
NSLog(#"Name: %#", [info valueForKey:#"name"]);
NSManagedObject *details = [info valueForKey:#"details"];
NSLog(#"Zip: %#", [details valueForKey:#"zip"]);
}
That looks as if the "details" property of "FailedBackInfo" is declared as
#property (nonatomic) int *details;
and not – as it should be – as
#property (nonatomic, retain) FailedBankDetails *details;
In the tutorial it says you can change the type of the info/detail variable in the h file depending on which one you create first manually. I found that this didn't work. I think your problem may be solved by deleting the subclass that you created first and then recreating it. That way it should link up with the entity relationships to info/detail (whichever you did second) properly

How to save and retrieve two arrays in Core Data in iOS6

I have two arrays
retrievedNamesMutableArray
retrievedImagesArray
which I am saving in Core Data. Although the saving operation is successful, when I fetch data, it seems to fetch either Names or Images but not both. I assume I can store a NSDictionary in Core Data but can't seem to figure out a way to do it.
This is what I am doing to save to Core Data.
-(void)saveToPhoneDatabase
{
AddressBookAppDelegate *appDelegate =[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newContact;
/* I assume this can be done but can't figure out proper process.
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
[dictionary setObject:self.retrievedNamesMutableArray forKey:#"NamesArray"];
[dictionary setObject:self.retrievedImagesArray forKey:#"ImagesArray"];
*/
for (NSString *object in self.retrievedNamesMutableArray)
{
newContact = [NSEntityDescription insertNewObjectForEntityForName:#"AddressBook" inManagedObjectContext:context];
[newContact setValue:#"GroupOne" forKey:#"groups"];
[newContact setValue:object forKey:#"firstName"];
}
for (UIImage *img in self.retrievedImagesArray)
{
newContact = [NSEntityDescription insertNewObjectForEntityForName:#"AddressBook" inManagedObjectContext:context];
[newContact setValue:img forKey:#"photo"];
NSLog(#"Saved the photos of Array");
}
[context save:nil];
}
This is how I fetch.
-(void)fetchFromPhoneDatabase
{
AddressBookAppDelegate *appDelegate =[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"AddressBook" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSError *error;
self.arrayForTable = [context executeFetchRequest:request error:&error];
NSLog(#"contents from core data = %#",self.arrayForTable);
[self.tableView reloadData];
}
Your first loop creates objects containing a name but no image, and your second loop create different objects containing an image but no name.
Assuming (from your previous questions) that both arrays have the same size, you should
create only one object for each name/image:
for (NSUInteger i = 0; i < [self.reterivedNamesMutableArray count]; i++) {
NSString *object = self.reterivedNamesMutableArray[i];
UIImage *img = self.reterivedImagesArray[i];
newContact = [NSEntityDescription insertNewObjectForEntityForName:#"AddressBook" inManagedObjectContext:context];
[newContact setValue:#"GroupOne" forKey:#"groups"];
[newContact setValue:object forKey:#"firstName"];
[newContact setValue:img forKey:#"photo"];
}

Why coredata is returning null array while I am inserting values in table

I have two methods,
In first method, I do save values in Core Data, while in other, I simply fetch them.
After inserting, when I fetch data in same method, it shows value, but when I try to fetch in other method if returns me null.
My saving Method is
-(void) saveloginData:(NSString *)facebookTok username:(NSString *)userName password:(NSString*)password flag:(NSString *)flag {
NSError *error;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"SignIn" inManagedObjectContext:context]];
[fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSString *facebookTokenData = facebookTok;
NSString *usernameData = userName;
NSString *passwordData = password;
NSString *flagData = flag;
NSLog(#"Facebook Token%#\nUsername%#\npassword%#\nflat%#\n",facebookTokenData,usernameData,passwordData,flagData);
SignIn *signIn = [NSEntityDescription
insertNewObjectForEntityForName:#"SignIn"
inManagedObjectContext:context];
signIn.facebookToken = facebookTokenData;
signIn.username = usernameData;
signIn.password = passwordData;
signIn.flag = flagData;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SignIn"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedArray = [context executeFetchRequest:fetchRequest error:&error];
for (SignIn *info in fetchedArray) {
\\ THis executes and shows values, proves that value are inserted.
NSLog(#"Name ~~~~ : %#", info.username);
NSLog(#"Password ~~~~~~~~ :%#", info.password);
NSLog(#"FLAG ~~~~~~~~~~~ %#",info.flag);
NSLog(#"Facebook Token %#", info.facebookToken);
}
}
My retrieve Method is
-(NSArray*) getLoginData {
NSError *error;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SignIn"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedData = [[NSArray alloc] init];
fetchedData = [context executeFetchRequest:fetchRequest error:&error];
NSLog(#"The count of Array %d", [fetchedData count]); \\ HERE COUNT IS ZERO, WHY?
for (SignIn *info in fetchedData) {
NSLog(#" FF Name ~~~~ : %#", info.username);
NSLog(#"Password ~~~~~~~~ :%#", info.password);
NSLog(#"FLAG ~~~~~~~~~~~ %#",info.flag);
NSLog(#"Facebook Token %#", info.facebookToken);
}
return fetchedData;
}
Please guide that where I am doing mistake.
Your problem is that you need to save conext to get the entity it later.
NSManagedObjectContext save: Attempts to commit unsaved changes to registered objects to their persistent store.
- (BOOL)save:(NSError **)error
Parameters: error: A pointer to an NSError object. You do not need to create an NSError object. The save operation aborts after the first failure if you pass NULL.
Return Value YES if the save succeeds, otherwise NO.
So you need to save context after you modify your object:
signIn.facebookToken = facebookTokenData;
signIn.username = usernameData;
signIn.password = passwordData;
signIn.flag = flagData;
[context save:NULL]; // NULL if you don't need to handle error

Resources