Could not get data from coredata - objective-c

I am getting an image from photo library and saving it to core data and then showing it to an image view. This is correctly working. But when i run project again the image is not showing on my image view.
This is code for getting image from photo library
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:YES];
UIImage *img= [info objectForKey:#"UIImagePickerControllerOriginalImage"];
NSManagedObjectContext *context=[self managedObjectContext];
NSManagedObject *newContact=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:#"Contacts" inManagedObjectContext:context] insertIntoManagedObjectContext:context];
//newContact = [NSEntityDescription insertNewObjectForEntityForName:#"Images" inManagedObjectContext:context];
NSData *data=UIImageJPEGRepresentation(img,0.0);
[newContact setValue:data forKey:#"image"];
[self fetchData];
}
This is the code of fetchData() method.
-(void)fetchData
{
NSManagedObjectContext *context=[self managedObjectContext];
NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Contacts"
inManagedObjectContext:context]];
NSError * error = nil;
NSArray * objects = [context executeFetchRequest:request error:&error];
if ([objects count] > 0) {
NSManagedObject *managedObject = objects[0];
data1 = [managedObject valueForKey:#"image"];
image2 = [[UIImage alloc]initWithData:data1];
_imageView.image=image2;
}
}
This is my viewDidLoad()
- (void)viewDidLoad
{
[super viewDidLoad];
[self fetchData];
// Do any additional setup after loading the view.
}

First you should save image path (not uiimage) to Core Data and then get the path from Core Data and load image to your imageView by this path.
And use Magical Record (https://github.com/magicalpanda/MagicalRecord) for managing Core Data and you will have no problem with it at all.

You modify your coredata context by setting an entity but you don't save the modifications. It is for this reason that it is not saved when you run your project again.
To fix it you must save your NSManagedObjectContext context after modifications by simply using save method.
So, at the end of your fetchData method, try to make :
[context save:nil];
(You can pass a NSError in parameter to get errors during save.)

do this after all modifications on coredata
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}

To save:
[newChannelToCoreData setValue:UIImagePNGRepresentation(_currentChannelImage) forKey:#"image"];
To fetch:
_currentChannelImage = [UIImage imageWithData:[lastChannel valueForKey:#"image"]];

Related

Core Data table getting wiped out when implementing background fetch for app icon badge in iOS7

I am trying to implement a background fetch in my AppDelegate.m to get the app icon badge to reflect an updated record count by pulling the latest record count from a web service via RestKit (not shown here). When I simulate a BackGroundFetch in Xcode everything works fine. When the background fetch runs on my iPhone 5S, my entire table "TicketList" gets wiped out with no data. Here is the code. Has anyone experienced anything similar and can anyone offer some advice as to what i am doing wrong? I've taken out the ReskKit lookup to simplify the code and debug to see if it would have any affect. I've looked at other postings and haven't been able to find an answer as to why this is happening.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//Added this code for the app icon badge functionality
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^) (UIBackgroundFetchResult))completionHandler
{
[UIApplication sharedApplication].applicationIconBadgeNumber = 1;
completionHandler(UIBackgroundFetchResultNewData);
}
*/
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
intAvailCount = 0;
[self setUpCoreDataStack];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"TicketList" inManagedObjectContext:context];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
self.ticketListData = [[context executeFetchRequest:fetchRequest error:&error] mutableCopy];
if ([ticketListData count] != 0){
//Perform loop through TicketList SQLite DB and count using intAvailCount
TicketList *info = [ticketListData objectAtIndex:0];
for (info in ticketListData) {
//Check to see if tickets in table have been added to do
intAvailCount++;
}
//End Loop
}
[UIApplication sharedApplication].applicationIconBadgeNumber = intAvailCount;
completionHandler(UIBackgroundFetchResultNewData);
}
-(void)setUpCoreDataStack
{
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:[NSBundle allBundles]];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSURL *url = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:#"TicketList.sqlite"];
NSDictionary *options = #{NSPersistentStoreFileProtectionKey: NSFileProtectionComplete,
NSMigratePersistentStoresAutomaticallyOption:#YES};
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error];
if (!store)
{
NSLog(#"Error adding persistent store. Error %#",error);
NSError *deleteError = nil;
if ([[NSFileManager defaultManager] removeItemAtURL:url error:&deleteError])
{
error = nil;
store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error];
}
if (!store)
{
// Also inform the user...
NSLog(#"Failed to create persistent store. Error %#. Delete error %#",error,deleteError);
abort();
}
}
self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.managedObjectContext.persistentStoreCoordinator = psc;
}
Problem solved. I moved the call to setUpCoreDataStack to the 1st method in my example (didFinishLaunchingWithOptions) which gets called on app startup and my problem was solved. Not exactly sure why this was happening in the 1st place but, i think it had something to do with my setUpCoreDataStack being called every time the perform background fetch method got triggered.

Core Data NSInternalInconsistencyException on single background thread delete function

My project has a database handler and one of its function is delete almost all records from the database. I execute the actual deleting on a single background thread. Sometimes my code works fine sometimes it crashes with a NSInternalInconsistencyException. Currently it fails 1 out of 3 tries. Why am I getting a NSInternalInconsistencyException? I thought this only happens when your multi-threading your core data function. Here's my code:
//Database handler init.
- (id)init
{
self = [super init];
if(self) {
self.appDelegate = [UIApplication sharedApplication].delegate;
//getting the managedobjectcontext from appdelegate
self.managedObjectContext = self.appDelegate.managedObjectContext;
//background queue
self.backgroundQueue = dispatch_queue_create("database.queue", NULL);
status = 0;
}
return self;
}
//delete majority of the database entry
- (void) clearTables
dispatch_async(self.backgroundQueue, ^(void) {
NSError *error;
//update this entity records.
for(Entity1 *object in [self queryEntity:#"Entity1"]) {
object.download_ymdhms = nil;
[self.managedObjectContext save:nil];
}
[self.managedObjectContext save:&error];
NSLog(#"error1: %#", [error localizedDescription]);
//Delete the other entities data.
for(Entity2 *object in [self queryEntity:#"Entity2"]) {
[self.managedObjectContext deleteObject:object];
}
[self.managedObjectContext save:&error];
NSLog(#"error2: %#", [error localizedDescription]);
for(Entity3 *object in [self queryEntity:#"Entity3"]) {
[self.managedObjectContext deleteObject:object];
}
...
for(Entity10 *object in [self queryEntity:#"Entity10"]) {
[self.managedObjectContext deleteObject:object];
}
[self.managedObjectContext save:&error];
NSLog(#"error3: %#", [error localizedDescription]);
//notify deletion complete
[[NSNotificationCenter defaultCenter] postNotificationName:#"database.queue.delete.done" object:nil];
});
}
//get all the objects in an entity.
- (NSArray *) queryEntity: (NSString *)entity {
return [self queryEntity:entity withPredicate:nil withLimit:0 orderBy:nil];
}
...
//general query
- (NSArray *) queryEntity: (NSString *)entity withPredicate: (NSString *)predicate withLimit: (int)limit orderBy: (NSString *)order
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:entity inManagedObjectContext:self.managedObjectContext]];
if(predicate.length > 0) {
[fetchRequest setPredicate:[NSPredicate predicateWithFormat: predicate]];
}
if(limit > 0) {
[fetchRequest setFetchLimit:limit];
}
if(order.length > 0) {
[fetchRequest setSortDescriptors: #[[[NSSortDescriptor alloc] initWithKey:order ascending:YES]]];
}
NSError *error;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
return results;
}
This is the error that I sometimes get:
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. statement is still active with userInfo (null)
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'statement is still active'
Edit: added code comments to make it more readable.

Update issue with Core Data

Trying to update some Core Data. The data is actually updating "somewhere", but its not saving/updating the db.
- (IBAction)Update:(id)sender {
NSEntityDescription *entityDesc =
[NSEntityDescription entityForName:#"Preferences"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSError *error;
NSArray *objects = [context executeFetchRequest:request
error:&error];
if ([objects count] == 0) {
// No update, didnt find any entries.
} else {
for (NSManagedObject *obj in objects) {
[obj setValue:_salesPrice.text forKey:#"value"];
if(![context save:&error]){
NSLog(#"Saving changes failed: %#", error);
}
}
}
//[context save:&error];
}
I've tried [context save:&error]; in the commented area, but still no save. I also get no error on save.
You use only 1 NSManagedObjectContext? Your naming convention is not ideal. Usually you would name the entity Preference, since its one object. Try the following code.
CoreDataAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
// This is for completion. Usually you should not get the context from the App Delegate.
// Its better to pass it from the App Delegate to
// the initial view controller via a property (dependency injection).
NSFetchRequest *req = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([Preferences class])];
NSError *error = nil;
NSArray *preferences = [context executeFetchRequest:req error:&error];
// Check error
if ([preferences count] == 0) {
// No update, didnt find any entries.
} else {
for (Preferences *preference in preferences) {
[preference setValue:_salesPrice.text forKey:#"value"];
}
}
[context save:&error];
// Check error

Predicate required in Core Data fetch request?

I would like to omitt the predicate in an NSFetchRequest in order to delete all managed objects for an entity.
However, when there is no predicate (according to the SQL debugger), the fetch request is not executed. According to Apple the predicate should be optional.
How would I need to change my code to remove the predicate? Any ideas? Thank you!
- (void)deleteEntity:(NSString*)entityName inContext:(NSManagedObjectContext *)context
{
NSFetchRequest * request= [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"TableStructure" inManagedObjectContext:context]];
//[entities setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"category = 'est'"];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *entitiesArray = [context executeFetchRequest:request error:&error];
if (error) {
NSLog(#"%#: Error fetching context: %#", [self class], [error localizedDescription]);
NSLog(#"entitiesArray: %#",entitiesArray);
return;
}
for(NSManagedObject *entity in entitiesArray) {
[context deleteObject:entity];
}
NSError *saveError = nil;
[context save:&saveError];
}
Update 2
It seems that I call my fetch request before the database is ready. How can I make sure that my request is not called before the core data database is ready?
You simply don't assign the predicate if you don't want it. Remove following lines:
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"category = 'est'"];
[request setPredicate:predicate];
I issued my fetch request before the Core Data database was ready.
To solve this issue, I have now added the call ImportFormulasInRequest to the UIDocument openWithCompletion handler, which encapsulates my core data database:
- (void)useDocument
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.myDatabase.fileURL path]]) {
// does not exist on disk, so create it
[self.myDatabase saveToURL:self.myDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
} else if (self.myDatabase.documentState == UIDocumentStateClosed) {
// exists on disk, but we need to open it
[self.myDatabase openWithCompletionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self ImportFormulasInContext:[self.myDatabase managedObjectContext]];
}];
} else if (self.myDatabase.documentState == UIDocumentStateNormal) {
// already open and ready to use
[self setupFetchedResultsController];
[self ImportFormulasInContext:[self.myDatabase managedObjectContext]];
}
}

iOS: [self.fetchedResultsController performFetch:&error]; makes my app to crash

I have a UITableViewController, and I want to feed it with the content of a core data model.
However, when I fetch the content my app crashes. This is the init method (I pass a NSManagedObjectContext to it).
- (id)initInManagedObjectContext:(NSManagedObjectContext *)context
{
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Document" inManagedObjectContext:context];
request.predicate = nil;
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"idDoc"
ascending:YES]];
/*
NSError *error = nil;
NSManagedObject *retrievedDocument = [[context executeFetchRequest:request error:&error] lastObject];
NSLog(#"retrievedDocument %#", retrievedDocument);
*/
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:#"CollectionCache"];
self.fetchedResultsController = frc;
[frc release];
[request release];
//HERE IT CRASHES
NSError *error;
[self.fetchedResultsController performFetch:&error];
if (error) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
//exit(-1); // Fail
}
}
return self;
}
I'm sure the context is correctly passed because if I uncomment the commented snippet, the stored data are correctly printed.
My guess is that something is wrong with the fetchedResultsController.
thanks
The exception was related to your wrong use of performFetch:
It returns a BOOL that tells you the success of the fetch. If you get a NO back you are allowed to check the NSError object. Otherwise you must not touch it.
Probably all the methods that use &error should be used like this:
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
//exit(-1); // Fail
}
The exception was not related to fetchedResultsController but due to the not initialized NSError
NSError *error = nil;