Deleting Information from Core data - objective-c

I have a app that parses all my data from my web service as soon as the app is loaded however I want to add an IBACTION (Button) that will delete all of the data from the coredata and reparse the information (therefore updating the data base) - like a Refresh Button.
The Method that call the parsing is:
- (void)getRssData
{
self.webServiceAndParser = [[LukesParser alloc] initWithDelegate:self];
[self.webServiceAndParser getAllData];
}
The core data method im using the build the object in my fetch results controller is:
- (void)insertNewObject
{
// Create a new instance of the entity managed by the fetched results controller.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[newManagedObject setValue:[NSDate date] forKey:#"timeStamp"];
// Save the context.
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
any ideas?

If you're deleting all the data in your Core Data persistent store, then see Delete/Reset all entries in Core Data? for some possible approaches.

Related

cannot bind array controller to a nested one to many relationship

I have 3 entities in my data model which are connected as follow:
User<-->>Performance<-->>Trials
Meaning that every user has several performances, in each he/she goes under several trials.
For each entity, I have one table view and one array controller object. For all, I have bound their Managed Object Context parameter to App Delegate.
Then I bound PerformanceArrayController to UserArrayController Content Set (Controller Key: selection and performances relationship). And the same for TrialArrayController: I bound it to PerformanceArrayController (on selection) and trials relationship.
I have no problem in binding single columns of User table view and performance table view to entities attributes. but when I want to do the same for trial table view, first I don't get autocompletion and second when I write the name of the attributes manually, I get a gray exclamation mark. and only the first trial is saved this way but not the rest of them.
Here is my function for inserting into Trial:
- (void) insertIntoTrial: (NSString *) result
{
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error;
Trial *trial = [NSEntityDescription insertNewObjectForEntityForName:#"Trial" inManagedObjectContext:context];
trial.result = result;
trial.time = [NSNumber numberWithDouble:[cueTimestamp timeElapsedInSeconds]];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Performance" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"user.fName==%#", userName]];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (Performance *performance in fetchedObjects) {
[performance addTrialsObject:trial];
trial.performance = performance;
}
if (![context save:&error]) {
NSLog(#"couldn't save Trial info: %#", [error localizedDescription]);
}
}
Thanks in advance,

Core Data Reading Data

I am a VERY new beginner to Core Data and I have recently been trying to read and write data. I created an entity named "Person" with the entities "name" and "age". I also have a textfield name "personName" and a textfield named "personAge".
- (IBAction)readData:(id)sender
{
NSNumber *ageNum = [NSNumber numberWithInteger:personAge.text.integerValue];
Person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:managedObjectContext];
newPerson.name = personName.text;
newPerson.age = ageNum;
NSLog(#"Person %# name is %#", personName.text, ageNum);
}
When I load the app, all i get is SIGABRT. Even when all I put in the method is
Person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:managedObjectContext];
All help is appreciated.
For Adding values to the core data you can do so:-
- (IBAction)save:(id)sender {
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:context];
[person setValue:self.personName.text forKey:#"name"];
[person setValue:self.personAge.text forKey:#"age"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
}
For fetching the values from core data:-
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Person"];
self.personValues = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
here personValues is a NSMutableArray.
For better understanding about these please go through this link.
http://www.appcoda.com/introduction-to-core-data/
Hope this will help you out.
If you are very new to Core Data, try using the MagicalRecord library which provides a series of helper categories for dealing with a lot of the boiler plate setup of Core Data.
Which brings me to the question you are asking: are you sure your Core Data stack is being setup correctly? Check to make sure your Managed Object Context is valid along with a proper Persistent Store Coordinator.
Best thing to do: put a breakpoint during the Core Data stack setup and step through it making sure everything is setup properly. Or install MagicalRecord and do one method call to [MagicalRecord setupAutomigratingCoreDataStack]...

NSIncrementalStore: Object's persistent store is not reachable from this NSManagedObjectContext's coordinator

I am trying to implement an NSIncrementalStore which will access a server over an RPC API. It needs to cache all the data locally, and so I have started by creating a NSIncrementalStore to use another core data stack which is used as the cache.
So first I set up the metadata and set up the core data stack that the cache will use. The cache SQL file is the URL passed in when the store is initialised:
- (BOOL)loadMetadata:(NSError *__autoreleasing *)error {
NSMutableDictionary *mutableMetadata = [NSMutableDictionary dictionary];
[mutableMetadata setValue:[[NSProcessInfo processInfo] globallyUniqueString] forKey:NSStoreUUIDKey];
[mutableMetadata setValue:RTkCachedAPIStoreType forKey:NSStoreTypeKey];
//[mutableMetadata setValue:NSStringFromClass([self class]) forKey:NSStoreTypeKey];
[self setMetadata:mutableMetadata];
// Set up the Cache Stack
NSManagedObjectModel *model = [self.persistentStoreCoordinator.managedObjectModel copy];
self.cacheModel = model;
self.cachePersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.cacheModel];
self.cacheContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSURL *storeURL;
if ([self.URL isFileURL]) {
storeURL = self.URL;
}
NSError *storeAddError = nil;
if (![self.cachePersistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:&storeAddError]) {
NSLog(#"Fatal error while creating persistent store: %#", storeAddError);
abort();
}
[self.cacheContext setPersistentStoreCoordinator:self.cachePersistentStoreCoordinator];
return YES;
}
The execute request for a simple request for an entity look like the following code. Essentially I'm just taking the request, wrapping it up as a FetchRequest and performing the request on the Cache Core data stack. I then create the objects using the returned objectID's on the calling context:
- (id)executeRequest:(NSPersistentStoreRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error {
if ([request requestType] == NSFetchRequestType) {
NSFetchRequest *fetchRequest = (NSFetchRequest *)request;
NSEntityDescription *entity = [fetchRequest entity];
NSFetchRequest *cacheFetchRequest = [[NSFetchRequest alloc] init];
cacheFetchRequest.entity = entity;
__block NSArray *fetchedObjectFromCache;
[self.cacheContext performBlockAndWait:^(){
fetchedObjectFromCache = [self.cacheContext executeFetchRequest:cacheFetchRequest error:error];
}];
NSMutableArray *fetchedObjects = [NSMutableArray arrayWithCapacity:[fetchedObjectFromCache count]];
for (NSManagedObject *anObject in fetchedObjectFromCache) {
NSManagedObjectID *objectID = anObject.objectID;
NSManagedObject *managedObject = [context objectWithID:objectID];
[fetchedObjects addObject:managedObject];
}
return fetchedObjects;
}
}
When I try this out it throws an exception with the error
<unknown>:0: error: -[] : Object's persistent store is not reachable from this NSManagedObjectContext's coordinator
at the lineNSManagedObject *managedObject = [context objectWithID:objectID]; I can't work out why this is - this is the exact way that apple suggest this is done in the docs!
This error seems to be associated with accessing a context across threads - but I'm not doing that.
Any suggestions as to what is wrong here?
You're using the wrong objectID.
The objectID from your cache will not match the objectID of your persistent store because your incremental store does not have the same identifier.

How to clear selected objects in NSManagedObjectContext

I have the following code that currently clears all the objects in my NSManagedObjectContext:
- (void)clearObjectList:(NSString *)identifier
{
// TODO: Delete any entries with the identifier at the start of the object's name
NSLog(#"Clearing the URL list...");
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSFetchRequest * fetch = [[NSFetchRequest alloc] init];
[fetch setEntity:[NSEntityDescription entityForName:#"URL" inManagedObjectContext:context]];
NSArray * result = [context executeFetchRequest:fetch error:nil];
for (id basket in result)
{
// Code here to check if we should delete this object
[context deleteObject:basket];
}
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
//abort();
}
}
The Data model I have for URL is:
dateAccessed: Date
name: String
url: String
I want to access the objects key name to determine if it should be removed. How do I access this?
Try this:
for(URL *basket in result)
{
if([basket.name isEqualToString:identifier])
[context deleteObject:basket];
}
When looping through your results, you know that all you'll get back is NSManagedObjects. Or, if you've created NSManagedObject subclasses, you'll only get back URL objects. Thus, you can replace id with either NSManagedObject * or URL * in your for loop.
If you did create subclasses, which I'd recommend, you can access the name with dot notation: basket.name. If you didn't, you can access it by calling [basket valueForKey:#"name"].

Core Data Objective C update content of Entity

I am first time asking question here, sorry, but I can not find similar one.
So, I need update data in Entity "City" attribute - #"name".
for Example in my Core Data I already have #"New York", #"Boston".
And by parsing XML I have NSMutableArray *Cities = (#"New York", #"Boston", #"Los Angeles", #"Washington");
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSString *attributeString = #"name";
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
//save to the TableView
cell.textLabel.text = [[object valueForKey:attributeString] description];
if ((indexPath.row + 1) == numberOfSectionsInTableView && (self.isParsingDone))
[self.insertNewObjectToCities:nil];
//When coredata updating - tableView is also updating automatically
//Here is just adding new data, but I do not know how to update
- (void)insertNewObjectToCities_translation:(id)sender
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
NSString *attributeString = #"name";
if (![[self.parseCities.Cities objectAtIndex:i] isEqualToString:[newManagedObject valueForKey:attributeString]])
{
[newManagedObject setValue:[self.parseCities.Cities objectAtIndex:i] forKey:attributeString];
NSLog(#"OBBB %#", [self.parseCities.Cities objectAtIndex:i]);
NSLog(#"dessss %#", [[newManagedObject valueForKey:attributeString] description]);
i++;
if (i==[self.parseCities.Cities count])
{
i = 0;
return;
}
else
{
NSLog(#"valueForKey %#", [newManagedObject valueForKey:attributeString]);
[self insertNewObjectToCities_translation:nil];
}
}
else
{
NSLog(#"else");
return;
}
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
To update a managed object, you first need to fetch it, make any changes to the fields in the fetched NSManagedObject, and then save the context you used to fetch the object. If you call insertNewObjectForEntityForName again, it will insert a new managed object every time, even if it already exists in Core Data.
It's quite slow to fetch a single object every time you need to check and see if a new one needs to be added. You might want to cache the objects you currently have loaded (or their unique identifying field) into an NSArray or NSSet so you can check that for membership, instead.