iOS 6 Core Data Relation Object insertObject issue - ios

In the below example code I am passing amanagedContext object via a property of the view controller this selector lives in. In this case this property is currentPetCoreDataObject.
Does someone have a simple project, not necessarily iOS project, that has a one to many relationship in it using the Core Data framework? A simple command-line app would do. All the examples with relationships that I can find are one to one.
I don't know how to use the generated selector in the xCode Generated entity class and couldn't find any examples:
- (void)insertObject:(Feeding *)value inPetFeedRelationAtIndex:(NSUInteger)idx;
The following code appears to work but when checking the count, it doesn't appear to be saving. What am I missing?
I am new to Core Data and have not yet successfully used a relation.
if (!self.nsMutableOrderedSetFeed)
{
NSLog(#"current feed count:%d", self.currentPetCoreDataObject.PetFeedRelation.count);
[self.addedFeedObject setBrand:self.txtBrand.text];
[self.addedFeedObject setFood:self.txtType.text];
[self.addedFeedObject setParentPetRelation:self.currentPetCoreDataObject];
[self.addedFeedObject addPetFeedRelationObject:self.addedFeedObject];
//[self.currentPetCoreDataObject insertObject:self.addedFeedObject inPetFeedRelationAtIndex:[self.currentPetCoreDataObject.PetFeedRelation i];
[self.currentPetCoreDataObject setPetFeedRelation:[self.nsMutableOrderedSetFeed initWithObject:self.addedFeedObject]];
}
NSError *error;
if (![self.managedObjectContext save:&error])
NSLog(#"Failed to add new Pet profile with error: %#", [error domain]);
[self dismissViewControllerAnimated:NO completion:nil];

Related

Core Data Requests from Today Extension returning 0 results?

I'm working on a simple app, and am looking to include some Core Data functionality from the Today Widget. It's giving me some trouble however, and I'm not sure what it is I'm missing.
Here's what I have done:
I've added the widget target to the Core Data model
I have NOT added my entity subclasses. This opens a can of worms with a bunch of sharedApplication references. I don't need to do much within the widget, so I think it will be much easier to just work with NSManagedObject instances.
In viewDidLoad of the widget I create a persistent container:
NSPersistentContainer *myContainer = [[NSPersistentContainer alloc] initWithName:#"MyDataModelName"];
[myContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
NSLog(#"Unresolved error %#, %#", error, error.userInfo);
abort();
}
}];
So far so good, and no error is returned.
However, no results are returned when I call:
[myContainer.viewContext executeFetchRequest:request error:&error];
Entity Name and predicates don't seem to make a difference. No request error is returned. Identical requests work fine within the app proper.
It would seem that I am maybe initiating an empty container instead of grabbing the correct one? I'm sure this is a simple thing, but I'm at a loss. Any help is appreciated.

Core Data - can't achieve a simple LightWeight Migration

I am unable to achieve a simple lightweight migration by simply adding 1 Entity to the datamodel.
I have read and followed all the guides/documentation/posts/answers, I can't seem to find my mistake/error.
I do have created a new datamodel from the already existing one.
I do have set the new datamodel as current datamodel.
I do have only added 1 Entity to the new datamodel (+ link to the parent Entity).
I do have passed the dictionary options NSMigratePersistentStoresAutomaticallyOption and NSInferMappingModelAutomaticallyOption in the method addPersistentStoreWithType.
I even tried to log everything, thank to the method given from this post: core data migration
/*! The method checks the Core Data file version is compatible with the App's model version
and then pushes the main menu view onto the navigation stack. If not compatible it displays a
message to the user.
#param file The file URL for the Core Data Store. With UIManagedDocument you have to get the
actual store file URL, you can't just use the UIManagedDocument file URL.
*/
-(void) checkCoreDataFileVersion:(NSURL*)file
{
if ([self checkVersion:file]) {
// file version is compatible so continue (add code to push the menu view)
} else {
// file version is NOT compatible
_fileOpenErrorAlert = [[UIAlertView alloc] initWithTitle:#"Unable to open Document" message:#"Please check that you have the correct application version installed" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[_fileOpenErrorAlert show];
}
return;
}
/*! Checks the Core Data files models version against the apps model version to see if they
are compatible. This will return YES if a lightweight migration can be performed and NO if NOT.
#param fileURL The file URL for the Core Data Store. With UIManagedDocument you have to get the
actual store file URL, you can't just use the UIManagedDocument file URL.
#return Returns YES if they are compatible and NO if not.
*/
- (bool)checkVersion:(NSURL*)fileURL {
NSManagedObjectModel *model = [self managedObjectModel];
NSLog(#" app model entity version hashes are %#", [model entityVersionHashesByName]);
NSError *error;
NSDictionary *metaData = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:fileURL error:&error];
if (!metaData) {
NSLog(#"problem getting metaData");
NSLog(#" - error is %#, %#", error, error.userInfo);
return NO;
}
bool result = [model isConfiguration:nil compatibleWithStoreMetadata:metaData];
if (!result) {
NSLog(#" file is not compatible!");
NSLog(#" metadata is %#", metaData);
}
return result;
}
When I make a diff of the metadata from all the Entities, I only match difference for 1 Entity (the newly created). So why it can't make a migration ? I just added 1 Entity.
EDIT :
I don't have Crashes, the App is working fine.
There is something I don't understand. When I download our lastest App from the AppStore, launch it and when I build from xCode my lastest developement App (with the new datamodel) over the one from the AppStore, the migration doesn't occur.
BUT when I use GIT, when I put the HEAD to the lastest release TAG, build, launch the App. Then put back the HEAD to my lastest development feature (with the new datamodel etc..), build and run, the migration is done and everything is working.
So which scenario should I trust ?
Yes, You should trust the 2nd senario to test coredata migration by applying it to the last released code.
The first senario is no more valid since Apple for some security reasons nomore give the ability to update an itune-downloaded app using xcode directly.
There was a way to test the upgrade on itune-version but not directly from xcode.
Technical Note TN2285
Testing iOS App Updates
Install an ad hoc distribution of an archived build of the update
using iTunes on a device that already has the old version of the app
installed.
Installing Your App on Test Devices Using iTunes

IOS Coredata. Is it possible to see saved data without fetching it

I am working on core-data base project. I want to know that is it possible to see which data are saved in coredata without fetching it ?
For example:
I am using this Tutorial to learn coredata. **
Core Data demo from AppCoda
I have implement below method to save the data in Data-model.(coredata)
- (IBAction)save:(id)sender {
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:#"Device" inManagedObjectContext:context];
[newDevice setValue:self.nameTextField.text forKey:#"name"];
[newDevice setValue:self.versionTextField.text forKey:#"version"];
[newDevice setValue:self.companyTextField.text forKey:#"company"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
but i want to know that, is it possible or is there any way to see what data are saved in my data model without Implement it's fetching method ?
Fetch From Coredata:
Yes. We can see saved data without fetching is .
After implement Save method core-data save sql file in Document Directory.
You can print it in nslog with using this Line.
NSLog(#"%#",[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
and you can see full path of document folder printed in log like this.
2015-10-13 12:40:51.253 MyStore[1860:69256] file:///Users/username/Library/Developer/CoreSimulator/Devices/C548BFA2-7B92-42E6-9D64-E16AFF0645D9/data/Containers/Data/Application/9C24913C-B295-4AA1-8DE9-A261CAA21624/Documents/
then you have to go in this folder. with selecting G0-> Go to folder... option.
Then print your Document path in go to folder window.
Note:- you have to write only this code in go to folder. (From ~/Library )
~/Library/Developer/CoreSimulator/Devices/C548BFA2-7B92-42E6-9D64-E16AFF0645D9/data/Containers/Data/Application/9C24913C-B295-4AA1-8DE9-A261CAA21624/Documents
and press GO button.
you will find your sqlfile.
open it with using some sqllite reader software.
SQL Lite pro this is the best software to read .sql file. open your file using it.
and you will see your saved data in it.
During runtime: No.
That is due the nature of Core Data. It is an object graph, not a data persistence solution. A fetch doesn't return an object if he can choose.
Outside of your app it depends on the persistence if any. If you decided to go for a sql store, then consider the sql answer. If you did select a different store type, then it depends on the type you went for.
For most projects are basic foundation objects fine since they can be serialized. If you parse an JSON you get foundation objects back. Consider Core Data when you deal with bigger data that need to be searchable even when you don't have the data in memory.

Duplicate NSManagedObjects in Core Data using MagicalRecord and MMRecord

Update 21/7/2014: I have found a workaround for the problem described here. I have created a separate NSManagedObjectContext called downloadContext. The downloaded serialized objects are put in that separate context. I then iterate through the response array and check if the object already exists in the MR_defaultContext (using the primary key).
If it does I update the properties from the downloaded object with the same primary key. It is not possible to simply copy the whole object and thus overwriting all properties of the existing object (because the updated object and the old one are in separate contexts). Instead I copy all properties of the downloaded object into an NSDictionary (dictionaryWithValuesForKeys) and then use setValuesForKeysWithDictionary to overwrite the properties of the old object. The same has to be done with the child objects.
If the object is new, I create a new object and copy the properties in the same way. I will need to check if this solution is efficient enough or if it will occupy too much memory in case there are many objects to download (first sync). The alternative is to create my own serialiser that decides on the basis of primary keys if to update an existing object or to create a new one.
For this issue, please note that I have seen the discussion on the relatedByAttribute key setting. It doesn't help in this case since this might only avoid duplicates of child relationship objects ( I haven't checked if there are duplicates). This is about the parent object duplicates.
In my project, I use AFNetworking, MMRecord and MagicalRecord together as dependencies. The situation is as follows:
I create a response serializer from the AFMMRecordResponseSerializer class which I simply set to my subclass object of the AFHTTPSessionManager. With this session manager I send a GET-request to the server. The response object already contains serialized NSManagedObjects (they are actually a subclass of MMRecord). I have set the MMRecordEntityPrimaryAttributeKey to each of the NSManagedObject's intended primary key. I think that the problem lies with MagicalRecords though, because it simply ignores MMrecord's primary attribute key setting.
After the initial GET-request with the persistent store still empty, there is no modification/creation date predicate. In case there are already persisted objects, the GET-request contains a predicate retrieving only objects after the last mod date from the server. So the updated object is persisted but the older object is not overwritten. When I display the titles of the objects in a table view I can see that the older version and updated version of an object are both displayed. Important: the table view is populated only from core data, not directly from the responseObject (containing the serialized objects).
Below is the most important code.
Thanks for any hints in the right direction
Dominik
-(void) fetchNotesFromServer
{
NSLog(#"fetchNotesFromServer called");
self.sessionManager.responseSerializer = [self getSerializerForEntityName:#"NAS_Notes" AndEndPointPathComponent:#"DBFetchNotes.php?"];
[self.sessionManager GET:[self getFetchNotesExtension] parameters:nil
success:^(NSURLSessionDataTask *task, id responseObject)
{
if (responseObject )
{
NSLog(#"fetch all notes response: %#", responseObject);
self.latestNotes = (NSMutableArray *)responseObject;
if ([self.latestNotes count] > 0)
{
[self saveDownloadedNotesInContext:[NSManagedObjectContext MR_defaultContext]];
}
}
} failure:^(NSURLSessionDataTask *task, NSError *error)
{
NSLog(#"NSerror %#", error);
}];}
-(void) saveDownloadedNotesInContext:(NSManagedObjectContext *)context{
[context MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
if (success) {
[self.delegate didFinishNotesSync:self];
}
else if (error) {
NSLog(#"error saving to persistent store %#", error);
}
}];
}

Magical Record appears to save, but changes are lost if app is terminated

I'm using Magical Record 2.1 to handle the data persistence in my app. If I create a new entity, set some it's attributes and save, it works fine. However, later, if I fetch that entity, update it's attributes and save, subsequent fetches have the new data until I terminate the app and restart. During the new app session the old data reappears.
This is how I create a new entity:
self.localContext = [NSManagedObjectContext MR_defaultContext];
self.theNewListing = [Listing MR_createInContext:self.localContext];
I'm using MRDefaultContext having read this blog post: http://saulmora.com/2013/09/15/why-contextforcurrentthread-doesn-t-work-in-magicalrecord/
In this case my main attribute is a dictionary, and I set it like this:
NSMutableDictionary *tempDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"A description", #"slFieldDescription", etc, etc, nil];
self.theNewListing.dataDictionary = tempDictionary;
This is how I save it:
[self.presentingViewController dismissViewControllerAnimated:YES completion:^(void) {
[self.localContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error){
if(!success) {
NSLog(#"%#", error);
}
else {
[self.thePresentingVC refreshCollectionViews:nil];
}
}];
}];
I display my data in a collection view, and at this point everything looks fine. If I terminate and restart the data is still there.
If I fetch the entity again and update the attributes like this:
NSMutableDictionary *newTempDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"A new description", #"slFieldDescription", etc, etc, nil];
self.theNewListing.dataDictionary = newTempDictionary;
Then save using the same save code as above, and then update my collection view using the code below, all looks good.
self.listingsArray = [[NSMutableArray alloc] initWithArray:[Listing MR_findAllSortedBy:#"dateListed" ascending:NO]];
[self.mainCollectionView reloadData];
That is, until I quit the app and restart.
If you're wondering, I'm using FTASync, and this only supports MR 2.1, which is why I haven't upgraded to the latest version.
Thanks!
Not sure about MR, nor why you would need it. If that framework can give you the main context, just call the native Core Data save.
[context save:nil];
Cracked it!!
I noticed that my other attributes were saving, just not this one (this one holds all the data that is presented in the UI) and this led me on another line of investigation.
So, it seems that I needed to be working with immutable dictionaries to store this data as explained here:
Core Data saving problem: can't update transformable attribute (NSArray)

Resources