How to insert NS Mutable Array into Core Data - iphone

-(void)dataManagerDidFinishLoading:(DataManager *)datamgr
{
NSLog(#"%#.....",datamgr);
pageArray=[datamgr.resultDataDictionary objectForKey:#"POS_GetPageResult"];
GetPage *page=(GetPage *)[NSEntityDescription
insertNewObjectForEntityForName:#"GetPage"
inManagedObjectContext:managedObjectContext];
NSError *error;
if (![managedObjectContext save:&error]) {
// This is a serious error saying the record could not be saved.
// Advise the user to restart the application
NSLog(#"Error........");
}
[pageArray insertObject:page atIndex:0];
}

Use NSKeyedArchiver:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
Note that all the objects in array must conform to the NSCoding protocol. If these are custom objects, then that means you need to read up on Encoding and Decoding Objects. You can store the NSData as BLOB in the database. Hope this helps you.

You can use the transformable core data type. Then your object will be parsed to an id. Just keep in mind that the transformable attribute will be passed to a NSData object (and reversed) to be stored (or retrieved) in core data.

Related

Core Data get back subclassed NSManagedObject from its objectID

I have 3 entities that I generated with MOGenerator, I'd like to be able to get one of them back from their objectID
I tried this :
- (void)aMethod: (SpecialEntity1ID *)entityID
{
//This is a method from MagicalRecord but it doesn't matter(I think...).
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]];
SpecialEntity1 *entity1 = [context objectRegisteredForID:entityID]
//But this returns an NSManagedObject so it doesn't work...
}
Could someone help me get this object back with its ID ?
Since I don't know how to do it with the ID I'm currently working around it by making a method with an NSStringas a paramater instead of SecialEntity1ID that defines one of the attribute of this object (and is unique) and fetching the object.
I think getting back with his ID is better so any idea ?
You want to use existingObjectWithID:error: method of your NSManagedObjectContext and typecast the return type if you are 100% sure what it will be. I'd keep it generic i.e. let it return an NSManagedObject and then test its class elsewhere if you want to determine whether it belongs to a particular class.
- (Object*)retrieveObjectWithID:(ObjectID*)theID
{
NSError *error = nil;
Object *theObject = (Object*)[[NSManagedObjectContext contextForCurrentThread] existingObjectWithID:theID error:&error];
if (error)
NSLog (#"Error retrieving object with ID %#: %#", theID, error);
return theObject;
}

Does coredata save after a change like this?

I have CoreData in my app, with an Entry class, which contains an NSOrderedSet of Media classes.
I then have this code, for adding a new Media item to the NSOrderedSet:
-(void)addImage:(UIImage *)image isInPhotoLibrary:(BOOL)isInPhotoLibrary {
Media *media = [[Media alloc] init];
media.type = #"Image";
media.originalImage = UIImageJPEGRepresentation(image, 1.0);
media.isInPhotoLibrary = [NSNumber numberWithBool:isInPhotoLibrary];
[self addMediaObject:media];
}
Will this automatically save the changes, or will I have to do it myself. If so, will i then need to pass in a context to do this, or is there another way?
No, this code doesn't have any Core Data references at all.
Is Media an NSManagedObject? If so you need to be creating it like so:
Media *media = [NSEntityDescription insertNewObjectForEntityForName:#"Media" inManagedObjectContext:context];
This will put it in your managed object context.
If you then want to persist it, you will need to call save: on the managed object context.
EDIT ALSO....
In your Entry class, you will probably have a generated method that you use to add objects to the NSSet. It will be in a category (CoreDataGeneratedAccessors) on the Entry header file
- (void)addMediaObject:(Media *)value;
No it won't.. If you want to save changes to Database in Core data you gotta call save function for that.. I assume Media is kind of NSManagedObject class. To save the changes to persistent store you have to call save method . Until then the changes are just temporary present on your scratch board/ ManagedObjectContext.
This is how I save changes:
Worker *worker = (Worker *)[NSEntityDescription insertNewObjectForEntityForName:#"Worker" inManagedObjectContext:self.managedObjectContext];
worker.name=txtContact.text;
worker.address=txtAddress.text;
worker.zipCode=txtZip.text;
worker.city=txtCity.text;
worker.mobile=txtMobile.text;
NSError *error;
if (![managedObjectContext save:&error])
{
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}

insert NSDictionary into CoreData

I have an NSDictionary and a CoreData Database. I want to insert the NSDictionary into the database.
How can I do this (code snippets if possible)?
What is the suitable type for the attribute of the dictionary ?
You would need to serialize your NSDictionary to an NSData, CoreData can hold to NSData.
But you won't be able to search (predicate) element of your NSDictionary.
And if we think about this, NSDictionary is a collection of data.
A Table in a database is kind of a collection of data.
In CoreData the closest thing you got to a collection of data is NSManagedObject.
So my advice would be to make a NSManagedObject subclass that would hold the information you have in your NSDictionary. The key would be the attribute and the value would be the value of that attribute. And you would be able to search based on the attribute of that NSManagedObject subclass.
I found another way to add Dictionary into Coredata by creating an attribute with data type 'Transformable'.
For example create an entity in your project & attribute with data type Transformable.
Generate subclass for NSManagedObject. Attribute will be available with data type 'id', change into NSDictionary.
Below is what I did (My NSManagedObject sub class name is 'DictTest')
-(void)InsertIntoDataBase
{
DictTest *entityDict=(DictTest*)[NSEntityDescription insertNewObjectForEntityForName:#"DictTest" inManagedObjectContext:self.managedObjectContext];
NSMutableDictionary *mutDict=[NSMutableDictionary dictionary];
[mutDict setValue:#"1" forKey:#"1"];
[mutDict setValue:#"2" forKey:#"2"];
[mutDict setValue:#"3" forKey:#"3"];
[mutDict setValue:#"4" forKey:#"4"];
[mutDict setValue:#"5" forKey:#"5"];
[mutDict setValue:#"6" forKey:#"6"];
[mutDict setValue:#"7" forKey:#"7"];
[mutDict setValue:#"8" forKey:#"8"];
[mutDict setValue:#"9" forKey:#"9"];
[mutDict setValue:#"10" forKey:#"10"];
[entityDict setInfoDict:mutDict];
NSError *error;
if(![self.managedObjectContext save:&error])
{
NSLog(#"error description is : %#",error.localizedDescription);
}
else{
NSLog(#"Saved");
}
}
for Fetching records
-(void)FetchRecord
{
NSFetchRequest *request=[[NSFetchRequest alloc]init];
NSEntityDescription *entity=[NSEntityDescription entityForName:#"DictTest" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSArray *fetchArray= [self.managedObjectContext executeFetchRequest:request error:nil];
for (DictTest *obj in fetchArray) {
NSLog(#"Dict is : %#",obj.infoDict);
}
}
Set up your entity description, insert a new object, then use:
[managedObject setValuesForKeysWithDictionary:dict];
Why don't you just create an entity with all the data from your NSDictionary and then just parse through it.
Check this out for some CoreData code snippets. You can simply create a few entities to store the info of your dictionaries. You can then parse through your dictionary and save the proper attributes:
NSManagedObject *photoObject = [NSEntityDescription insertNewObjectForEntityForName:#"Photo"
inManagedObjectContext:context];
[photoObject setPhotographer:[myDictionary objectForKey:#"photographer"]];
and so on...
No matter how complex you XML data structure, if you can set up a nice entity structure, it is fairly easy to simply dumb it all in CoreData. You'll also have a much easier time with queries if you take the time to create entities instead of just dumping the whole dictionary in a single field.

Integer to NSInteger And Save To Core Data

I have a integer named marbles, and am trying to save it into an array using the following code:
[records setValue:marbles forKey:#"marbles"];
With this code, I get the warning:
warning: Semantic Issue: Incompatible integer to pointer conversion sending 'int' to parameter of type 'id'
So, How do I set the value for an NSInteger.
Next Question, How do re-upload the array into core data? I fetch the array, make changes, and how do I apply those changes back to Core Data?
Thanks
Initialize an NSNumber (which is what CoreData is expecting) with your integer:
NSNumber *marbleNumber = [NSNumber numberWithInt:marbles];
[records setObject:marbleNumber forKey#"marbles"];
Or:
[records setMarbles:[NSNumber numberWithInt:marbles]];
To persist your changes, you save your context:
NSError *error;
[myManagedObjectContext save:&error];
//handle your error
NSArrays will only take objects, so the first step is to turn your NSInteger into a NSNumber using this method:
+ (NSNumber *)numberWithInt:(int)value
so:
NSNumber *myNumber = [NSNumber numberWithInt:marbles];
and then you can do:
[records setValue:myNumber forKey:#"marbles"];
Basically once you fetch the data, you get a managedObjectContext, think of it as a drawing board, and any changes (including adding or deleting new objects), you make to this objects may be saved again to CoreData using something like this:
NSError *error;
if (![context save:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
Where context is the context you would get with your NSFetchedResultsController. Which you can get like this:
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
I would recommend taking a look at the Core Data programming guide
- (id)primitiveValueForKey:(NSString *)key;
- (void)setPrimitiveValue:(id)value forKey:(NSString *)key;
use NSNumber in place of (id)value

Storing data from ObjectiveFlickr in a Singleton on iPhone

The goal is to have a singleton data controller class called FetchData.h/.m that pulls data using ObjectiveFlickr ( https://github.com/lukhnos/objectiveflickr ).
FetchData.m grabs the data with this:
OFFlickrAPIContext *context = [[OFFlickrAPIContext alloc] initWithAPIKey:YOUR_KEY sharedSecret:YOUR_SHARED_SECRET];
OFFlickrAPIRequest *request = [[OFFlickrAPIRequest alloc] initWithAPIContext:context];
// set the delegate, here we assume it's the controller that's creating the request object
[request setDelegate:self];
[request callAPIMethodWithGET:#"flickr.photos.getRecent" arguments:[NSDictionary dictionaryWithObjectsAndKeys:#"1", #"per_page", nil]]
and then implement the following delegate:
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary;
Currently I have this code to save the NSDictionary as a property list to a file as an alternative to a singleton:
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse: (NSDictionary *)inResponseDictionary{
if([inResponseDictionary writeToFile:#"inResponseDictionary.xml" atomically:TRUE])
{
NSLog(#"%#", [[NSFileManager defaultManager] fileExistsAtPath:#"inResponseDictionary.xml"]);
}
}
When I read this file back, I get Null. The file is read back as such:
NSDictionary *inResponseDictionary = [NSDictionary dictionaryWithContentsOfFile:#"inResponseDictionary.xml"];
NSDictionary *photoDict = [[inResponseDictionary valueForKeyPath:#"photos.photo"] objectAtIndex:0];
NSLog(#"%#", [photoDict count]);
Is there a better way to store this data from ObjectiveFlickr so that it can be accessed by other classes and view controllers? Or is there a better way to implement this in the View Controller.
What is in the returned NSDictionary? Are you sure they are all valid plist objects? The photo data might need to be modified (say, base 64 encoded into an array) before your write will work.
The docs for NSDictionary writeToFile: say
This method recursively validates that all the contained objects are property list objects (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.
As for the singleton aspect - will you be making more than one of these calls at a time? Is there a need to persist the data? If no & no, just keep the dictionary in memory. If you have multiple calls happening at once, you'll need another layer of abstraction (some indexing) to put each call's results in it's own unique location. And that's not happening with your current implementation.