Files
RestKit/Code/CoreData/RKFetchRequestManagedObjectCache.m
Blake Watters 8dc54a89b2 Major overhaul to the Core Data managed object identification and relationship connection support.
* Replaces primary key with `RKEntityIdentifier`
* Add support for use of compound keys for object identification
* Refactor `RKConnectionMapping` to `RKConnectionDescription` and add support for connecting with multiple attributes
* Clarify naming of representation key methods to better match naming conventions
* Add type transformation support for object identification
* Greatly expand test coverage for object identification
* Drop the `NSEntityDescription` category
* Simplify the `RKManagedObjectCaching` protocol
* Add compound key support to the Fetch Request and In Memory Cache implementations
* Replace Kiwi with Specta for tests where contexts are helpful for organization
* Rename `defaultValueForMissingAttribute` to `defaultValueForAttribute`
2012-11-27 10:29:36 -05:00

79 lines
2.9 KiB
Objective-C

//
// RKFetchRequestMappingCache.m
// RestKit
//
// Created by Jeff Arena on 1/24/12.
// Copyright (c) 2009-2012 RestKit. All rights reserved.
//
#import "RKFetchRequestManagedObjectCache.h"
#import "RKLog.h"
#import "RKPropertyInspector.h"
#import "RKPropertyInspector+CoreData.h"
// Set Logging Component
#undef RKLogComponent
#define RKLogComponent RKlcl_cRestKitCoreData
static NSString *RKPredicateCacheKeyForAttributes(NSArray *attributeNames)
{
return [[attributeNames sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] componentsJoinedByString:@":"];
}
// NOTE: We build a dynamic format string here because `NSCompoundPredicate` does not support use of substiution variables
static NSPredicate *RKPredicateWithSubsitutionVariablesForAttributes(NSArray *attributeNames)
{
NSMutableArray *formatFragments = [NSMutableArray arrayWithCapacity:[attributeNames count]];
for (NSString *attributeName in attributeNames) {
NSString *formatFragment = [NSString stringWithFormat:@"%@ = $%@", attributeName, attributeName];
[formatFragments addObject:formatFragment];
}
return [NSPredicate predicateWithFormat:[formatFragments componentsJoinedByString:@" AND "]];
}
@interface RKFetchRequestManagedObjectCache ()
@property (nonatomic, strong) NSCache *predicateCache;
@end
@implementation RKFetchRequestManagedObjectCache
- (id)init
{
self = [super init];
if (self) {
self.predicateCache = [NSCache new];
}
return self;
}
- (NSArray *)managedObjectsWithEntity:(NSEntityDescription *)entity
attributeValues:(NSDictionary *)attributeValues
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
{
NSAssert(entity, @"Cannot find existing managed object without a target class");
NSAssert(attributeValues, @"Cannot retrieve cached objects without attribute values to identify them with.");
NSAssert(managedObjectContext, @"Cannot find existing managed object with a nil context");
NSString *predicateCacheKey = RKPredicateCacheKeyForAttributes([attributeValues allKeys]);
NSPredicate *substitutionPredicate = [self.predicateCache objectForKey:predicateCacheKey];
if (! substitutionPredicate) {
substitutionPredicate = RKPredicateWithSubsitutionVariablesForAttributes([attributeValues allKeys]);
[self.predicateCache setObject:substitutionPredicate forKey:predicateCacheKey];
}
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[entity name]];
fetchRequest.predicate = [substitutionPredicate predicateWithSubstitutionVariables:attributeValues];
NSError *error = nil;
NSArray *objects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (! objects) {
RKLogError(@"Failed to execute fetch request due to error: %@", error);
}
RKLogDebug(@"Found objects '%@' using fetchRequest '%@'", objects, fetchRequest);
return objects;
}
@end