Search code examples
iosswiftobjective-cmacosnsfetchedresultscontroller

Generic way to create cache names for NSFetchedResultsController


I am writing an app with a lot of different NSFetchedResultsController instances which I create in a factory method.

Now I am trying to generically create a cache name for the controller from its attributes (concatenate entity name, predicate, sorting information...).

If anyone has done this before, please share your experience:

  • Is it a good approach?
  • How exactly should I create the cache name?

As a side thought:

I am also wondering why this isn't already handled by the NSFetchedResultsControllers implementation itself. Why would I ever want to manually assign some cache name, this seems to be an error-prone overhead! Or am I missing something here?


Solution

  • I am astonished, nobody seems to be interested. I would have guessed, everybody who deals with a lot of dynamically created resultsControllers would need this!

    Anyway, here is my solution:

    // NSFetchedResultsController+GenericCache
    
    - (id)initWithFetchRequest:(NSFetchRequest *)fetchRequest
          managedObjectContext:(NSManagedObjectContext *)context
            sectionNameKeyPath:(NSString *)sectionNameKeyPath
                      useCache:(BOOL)useCache {
        NSString *cacheId = nil;
        if (useCache) {
            cacheId = [NSString stringWithFormat:@"%@-%@-%@"
                       , sectionNameKeyPath
                       , [fetchRequest entityName]
                       , [[fetchRequest predicate] predicateFormat]];
            for (NSSortDescriptor *descriptor in [fetchRequest sortDescriptors]) {
                NSString *sortId = [NSString stringWithFormat:@"-%@-%@-%@"
                                    , [descriptor key]
                                    , ([descriptor ascending]) ? @"ascending": @"descending"
                                    , NSStringFromSelector([descriptor selector])];
                cacheId = [cacheId stringByAppendingString:sortId];
            }
        }
        return [self initWithFetchRequest:fetchRequest
                     managedObjectContext:context
                       sectionNameKeyPath:sectionNameKeyPath
                                cacheName:cacheId];
    }
    
    - (void)deleteCache {
        [[self class] deleteCacheWithName:[self cacheName]];
    }
    

    I am still testing and I am very open to critique & suggestions for improvement.

    Please help making this reliable.