1

I use a singleton for working with arrays etc. cross the views in the application.

To initialize the singleton and the NSManagedObjectContext, so that I can fetch objects, I use:

+(DataControllerSingleton *)singleDataController
{    
    static DataControllerSingleton * single=nil;

    @synchronized(self)
    {
        if(!single)
        {
            single = [[DataControllerSingleton alloc] init];            
            NSManagedObjectContext *context = [single.fetchedResultsController managedObjectContext];

            single.masterCareList = [[NSMutableArray alloc] init];
        }        
    }
    return single;
}

When I insert a new object that object will not show up in display functions until I restart the application. I insert new object through this method in the singleton class:

- (void)insertNewObject:(Care *)care
{
  NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];      

  NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];

  NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:  
   [entity name] inManagedObjectContext:self.managedObjectContext];

  NSString *fileName = care.pictureURL;
  NSString *text = care.causeText;
  NSDate  *date = care.date;
  NSData  *imgData = care.imageData;

  [newManagedObject setValue:fileName forKey:@"urlPath"];
  [newManagedObject setValue:text forKey:@"name"];
  [newManagedObject setValue:date forKey:@"date"];
  [newManagedObject setValue:imgData forKey:@"imageData"];

   // Save the context.
  [self saveContext];

  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();
  }
}

My count method is the way I can tell that the new object is not included until I restart the application. The count method is also in the singleton as well.

- (NSUInteger)countOfList
{        
    NSArray *fetchedData = [_fetchedResultsController fetchedObjects];
    return [fetchedData count];   
}

When calling singleton I use:

DataControllerSingleton *singletonData = [DataControllerSingleton singleDataController];    
[singletonData insertNewObject:care];

managedObjectContext property:

.h:

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

.m:

@implementation DataControllerSingleton

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

Why will not my new object show up in ex count until I restart application?

Am I somehow using different threads with different contexts, or different fethedResultsController or different singleton (shouldnt be possible right?)??


I added these two lines, which are not included in the genereated CoreData Stack, and it now works fine.

In singleton header:

@interface DataControllerSingleton : NSObject <NSFetchedResultsControllerDelegate>

In implementation file,

(NSFetchedResultsController *)fetchedResultsController {

    _fetchedResultsController.delegate = self;
djcj
  • 149
  • 2
  • 15
  • In the line `NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName: [entity name] inManagedObjectContext:self.managedObjectContext];` you reference `self.managedObjectContext` but do not show anywhere in your code where you set that property – ppilone Jul 02 '13 at 15:29
  • @ppilone I have a managedObjectContextProperty and synthesize in my singelton class. See updated question for code. – djcj Jul 03 '13 at 11:55
  • I want to find the person who is recommending the use of singletons for data access :) – Abizern Jul 03 '13 at 12:05
  • @Abizern well I can give him to you if you help me solved this!! Its actually quite nice with a singelton othwerwise.... – djcj Jul 03 '13 at 12:09
  • Are you observing the managed object context to know when changes are happening? Is your NSFetchedResultsController set up to do this, i.e. do you have a delegate for your NSFetchedResults Controller? – Abizern Jul 03 '13 at 12:12
  • @Abizern no I dont use a delegate as of now. The thing is, that if I dont try to "initialize it" in my singelton my count method and everything works fine after I call the create new object method. So in that case I dont need any delagates for the other views to know that there has been some changes. The idea was that the singelton do all the manipulation and datacontrol and therefore I dont need delegates. – djcj Jul 03 '13 at 12:17
  • So if I remove: NSManagedObjectContext *context = [single.fetchedResultsController managedObjectContext]; It works fine but only after I call the newObject method. – djcj Jul 03 '13 at 12:18
  • @Abizern ok, I've been testing around and I believe you are right regarding delegates. I am just not sure how to set it up? Would it be possible for you to reply with an answer with some hints? – djcj Jul 03 '13 at 13:16
  • There's a bunch of sample code in the relevant [NSFetchedResultsController](http://developer.apple.com/library/ios/#DOCUMENTATION/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intf/NSFetchedResultsControllerDelegate) documentation. – Abizern Jul 03 '13 at 14:01
  • How is your `managedObjectContext` property being set? Are you sure it's the same context you're using for your `NSFetchedResultsController`? in your `insertNewObject` method you save the context used by your `NSFetchedResultsController` but use your `managedObjectContext` property when inserting a new object. Are these the same context? – ppilone Jul 03 '13 at 14:10
  • @Abizern It was me http://stackoverflow.com/questions/16594039/core-data-context-and-singleton-data-controller/16596787#16596787 ;) In this case a singleton allows you to manage a Core Data Stack. Why singletons are bad in this case? – Lorenzo B Jul 03 '13 at 15:18
  • Just pass a context up the stack to objects that need them. It's in the [docs](http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html). Using a singleton is effectively the same thing as calling down to the app delegate for a context. – Abizern Jul 03 '13 at 15:24

1 Answers1

1

As I understand from your question, you are using a table or similar.

If you want to update the table as soon as you save the context you need to:

  1. Reload the data table [table reloadData];
  2. or implement in the correct delegate methods of (take a look to How To Use NSFetchedResultsController)

If you follow the first option, you can just do a save in the context and call realod data on the table.

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();
}

[table reloadData];

NOTE THAT YOU ARE CALLING THE SAVE TWICE Do it once. In this case I suppose that [self saveContext]; does the saving as above.

If you follow the second approach, the data reload woul be handled for you.

Hope that helps.

Edit

The delegate of your fetched results controller should be a view controller (the one that contains the table). Do not put it in your singleton!!

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • Why not in the singleton? It works :) My views are not "aware" of any Core Data functions or properties. – djcj Jul 05 '13 at 08:29
  • @djcj What option did you choose? – Lorenzo B Jul 05 '13 at 09:56
  • I set the singelton as a fetchedResultDelegate, thats about it. I'm not using a table. I generate pictures and they are then displayed in a historyView. So I fetch the pictures from core data. I updated the question with my updates. I first posted it as an suggested answer since it said: Answer your own question. But it was removed by moderator, which I found weird. Anyway I'm going with this for now. Thanks for the help! @flexaddicted – djcj Jul 06 '13 at 23:24