Search code examples
iosobjective-ccore-datansmanagedobjectnsmanagedobjectcontext

When are NSManagedObjects deallocated?


I have problem with deallocating my controller when I navigate back in hierarchy. I found that the problem would be with objects which are loaded from Core Data. When I comment out line with // * the controller is successfully deallocated but with line in place the NSLog isn't printed.

I extract code from controller:

@implementation ModulesListViewController {
  NSArray *_modules;
}

- (void)viewDidLoad {
  [super viewDidLoad];

  _modules = [[StorageManager manager] getModulesCDByUserEmail:userEmail]; // *
  ...
}

- (void)dealloc {
  NSLog(@"ModulesListViewController dealloc");
}

getModulesCDByUserEmail is method which fetch data from Core Data and returns NSArray. Nothing unusual. I guess the problem is with NSManagedObjectContext.

- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _managedObjectContext.parentContext = [self writerManagedObjectContext];

    return _managedObjectContext;
}

I have it in singleton and it's globally accessible so it's not deallocated. Is this a problem? Should I create own NSManagedObjectContext for each controller if I want to be properly deallocated? Could these contextes be NSMainQueueConcurrencyType? Or is there a way how can I deallocate objects fetched from context which isn't deallocated?

Thanks for help


Solution

    1. Do not create a NSManagedObjectContext for each view controller. There is no value in that.
    2. Instead of a singleton, consider using dependency injection. It is a better design that will save you headaches when you add testing or try and reuse view controllers.

    The array is not retaining your view controller so the array is not causing the retain issue. However, with that line of code commented out your _modules variable is nil which means other activity against that variable would have a nil response. I would suggest tracing that variable through your view controller and find out where you are causing a retain loop. It is not in that line of code.

    Also, consider using a @property instead of a direct ivar like this. It will allow more optimization from the compiler as well as letting ARC do its job better.

    Lastly, if this is a table view that you are working with, consider using a NSFetchedResultsController instead of your own array. You will get far superior performance with less code.