Skip to content

Instantly share code, notes, and snippets.

@ffried
Last active August 29, 2015 14:03
Show Gist options
  • Select an option

  • Save ffried/091e033402908ec98a66 to your computer and use it in GitHub Desktop.

Select an option

Save ffried/091e033402908ec98a66 to your computer and use it in GitHub Desktop.
NSManagedObject+FFFindAndOrCreate
//
// NSManagedObject+FFFindAndOrCreate.h
//
// Created by Florian Friedrich on 15.12.13.
// Copyright (c) 2013 Florian Friedrich. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
// Defines
#ifndef kNSManagedObjectFFFindOrCreateCrashOnError
#if DEBUG
#define kNSManagedObjectFFFindOrCreateCrashOnError YES
#else
#define kNSManagedObjectFFFindOrCreateCrashOnError NO
#endif
#endif
#ifndef kNSManagedObjectFFFindOrCreateDefaultCombineAction
#define kNSManagedObjectFFFindOrCreateDefaultCombineAction @"AND"
#endif
/**
* Some useful find and/or create extensions to NSManagedObject.
* @see NSManagedObject
*/
@interface NSManagedObject (FFFindAndOrCreate)
#pragma mark - Just create
/**
* Creates a managed object in a given managed object context with the class name as entity name.
* @param context The context in which to create the managed object.
* @return The new managed object instance or nil if an error occured.
*/
+ (instancetype)createObjectInManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Creates a managed object with a given entity name in a given managed object context.
* @param entityName The entity name of the new managed object.
* @param context The context in which to create the managed object.
* @return The new managed object instance or nil if an error occured.
*/
+ (instancetype)createObjectWithEntityName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context;
#pragma mark - Just find
// Single values
/**
* Find objects by a key and an objectValue in a given context and the class name as entity.
* @param key The key to which to match the objectvalue.
* @param objectValue The objectValue for the given key.
* @param context The context in which to search.
* @return An array of found objects (may be empty) or nil if an error occurred.
*/
+ (NSArray *)findObjectsByKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Find objects of a given entity by a key and an objectValue in a given context.
* @param entityName The entity of which to search instances.
* @param key The key to which to match the objectvalue.
* @param objectValue The objectValue for the given key.
* @param context The context in which to search.
* @return An array of found objects (may be empty) or nil if an error occurred.
*/
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Find objects of a given entity by a key and an objectValue in a given context.
* @param entityName The entity of which to search instances.
* @param key The key to which to match the objectvalue.
* @param objectValue The objectValue for the given key.
* @param context The context in which to search.
* @param error A pointer to a NSError in which to save any error.
* @return An array of found objects (may be empty) or nil if an error occurred.
*/
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error;
// Multiple values
/**
* Find objects by a key/objectValue dictionary in a given context and the class name as entity name.
* @param keyObjectDictionary The dictionary containing keys and objects to match.
* @param context The context in which to search.
* @return An array of found objects (may be empty) or nil if an error occurred.
*/
+ (NSArray *)findObjectsByKeyObjectValue:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Find objects of a given entity by a key/objectValue dictionary in a given context.
* @param entityName The entity of which to search objects.
* @param keyObjectDictionary The dictionary containing keys and objects to match.
* @param context The context in which to search.
* @return An array of found objects (may be empty) or nil if an error occurred.
*/
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Find objects of a given entity by a key/objectValue dictionary in a given context.
* @param entityName The entity of which to search objects.
* @param keyObjectDictionary The dictionary containing keys and objects to match.
* @param context The context in which to search.
* @param error A pointer to a NSError in which to save any error.
* @return An array of found objects (may be empty) or nil if an error occurred.
*/
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error;
#pragma mark - Find or Create
// Singleton objects
/**
* Finds or creates an object in a given managed object context and the class name as entity.
* @param context The context in which to search/create the object
* @return The singleton object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectInManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Finds or creates an object with a given entity in a given managed object context.
* @param entityName The entity of the object.
* @param context The context in which to search/create the object.
* @return The singleton object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Finds or creates an object with a given entity in a given managed object context.
* @param entityName The entity of the object.
* @param context The context in which to search/create the object.
* @param error A pointer to a NSError in which to save any error.
* @return The singleton object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error;
// Single values
/**
* Finds or creates an object with a given objectvalue for a given key in a given managed object context and the class as entity name.
* @param key The key of the objectvalue to match.
* @param objectValue The objectvalue of the key.
* @param context The context in which to search/create the object.
* @return The found/created object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectByKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Finds or creates an object with a given objectvalue for a given key and a given entity in a given managed object context.
* @param entityName The entity of the object.
* @param key The key of the objectvalue to match.
* @param objectValue The objectvalue of the key.
* @param context The context in which to search/create the object.
* @return The found/created object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Finds or creates an object with a given objectvalue for a given key and a given entity in a given managed object context.
* @param entityName The entity of the object.
* @param key The key of the objectvalue to match.
* @param objectValue The objectvalue of the key.
* @param context The context in which to search/create the object.
* @param error A pointer to a NSError in which to save any error.
* @return The found/created object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error;
// Multiple values
/**
* Finds or creates an object with given keys/objectvalues in a given managed object context with the class as entity.
* @param keyObjectDictionary The keys/objectvalues of the object to search/create.
* @param context The context in which to search/create the object.
* @return The found/created object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectByKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Finds or creates an object with a given entity and given keys/objectvalues in a given managed object context.
*
* @param entityName The entity of the object.
* @param keyObjectDictionary The keys/objectvalues of the object to search/create.
* @param context The context in which to search/create the object.
* @return The found/created object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context;
/**
* Finds or creates an object with a given entity and given keys/objectvalues in a given managed object context.
*
* @param entityName The entity of the object.
* @param keyObjectDictionary The keys/objectvalues of the object to search/create.
* @param context The context in which to search/create the object.
* @param error A pointer to a NSError in which to save any error.
* @return The found/created object or nil if an error occurred.
*/
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error;
@end
//
// NSManagedObject+FFFindAndOrCreate.m
//
// Created by Florian Friedrich on 15.12.13.
// Copyright (c) 2013 Florian Friedrich. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#import "NSManagedObject+FFFindAndOrCreate.h"
@implementation NSManagedObject (FFFindAndOrCreate)
#pragma mark - Just create
+ (instancetype)createObjectInManagedObjectContext:(NSManagedObjectContext *)context
{
return [self createObjectWithEntityName:NSStringFromClass(self)
inManagedObjectContext:context];
}
+ (instancetype)createObjectWithEntityName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
}
#pragma mark - Just find
#pragma mark Single values
+ (NSArray *)findObjectsByKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findObjectsByKeyObjectValue:@{key: objectValue} inManagedObjectContext:context];
}
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findObjectsWithEntityName:entityName
byKeyObjectDictionary:@{key: objectValue}
inManagedObjectContext:context];
}
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error
{
return [self findObjectsWithEntityName:entityName
byKeyObjectDictionary:@{key: objectValue}
inManagedObjectContext:context
withError:error];
}
#pragma mark Multiple values
+ (NSArray *)findObjectsByKeyObjectValue:(NSDictionary *)keyObjectDictionary inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findObjectsWithEntityName:NSStringFromClass(self)
byKeyObjectDictionary:keyObjectDictionary
inManagedObjectContext:context];
}
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findObjectsWithEntityName:entityName
byKeyObjectDictionary:keyObjectDictionary
inManagedObjectContext:context
withError:nil];
}
+ (NSArray *)findObjectsWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error
{
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:entityName];
if (keyObjectDictionary) {
NSMutableString *formatString = [[NSMutableString alloc] init];
NSMutableArray *argumentArray = [[NSMutableArray alloc] init];
[keyObjectDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
if (formatString.length > 0) {
[formatString appendFormat:@" %@ ", kNSManagedObjectFFFindOrCreateDefaultCombineAction];
}
[formatString appendString:[NSString stringWithFormat:@"%@ == %@", key, @"%@"]];
[argumentArray addObject:obj];
}];
fetchRequest.predicate = [NSPredicate predicateWithFormat:formatString.copy
argumentArray:argumentArray.copy];
}
NSError *__autoreleasing *errorPtr = error;
if (errorPtr == NULL) {
__autoreleasing NSError *localError = nil;
errorPtr = &localError;
}
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:errorPtr];
if (fetchedObjects == nil && *errorPtr != nil) {
NSLog(@"Error while executing findOrCreate fetch request: %@", *errorPtr);
#if kNSManagedObjectFFFindOrCreateCrashOnError
abort();
#endif
}
return fetchedObjects;
}
#pragma mark - Find or Create
#pragma mark Singleton objects
+ (instancetype)findOrCreateObjectInManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findOrCreateObjectByKeyObjectDictionary:nil inManagedObjectContext:context];
}
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findOrCreateObjectWithEntityName:entityName
byKeyObjectDictionary:nil
inManagedObjectContext:context];
}
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error
{
return [self findOrCreateObjectWithEntityName:entityName
byKeyObjectDictionary:nil
inManagedObjectContext:context
withError:error];
}
#pragma mark Single key/value methods
+ (instancetype)findOrCreateObjectByKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findOrCreateObjectByKeyObjectDictionary:@{key: objectValue}
inManagedObjectContext:context];
}
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findOrCreateObjectWithEntityName:entityName
byKeyObjectDictionary:@{key: objectValue}
inManagedObjectContext:context];
}
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKey:(NSString *)key
objectValue:(NSObject *)objectValue
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error
{
return [self findOrCreateObjectWithEntityName:entityName
byKeyObjectDictionary:@{key: objectValue}
inManagedObjectContext:context
withError:error];
}
#pragma mark Key/value dict methods
+ (instancetype)findOrCreateObjectByKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findOrCreateObjectWithEntityName:NSStringFromClass(self)
byKeyObjectDictionary:keyObjectDictionary
inManagedObjectContext:context];
}
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
{
return [self findOrCreateObjectWithEntityName:entityName
byKeyObjectDictionary:keyObjectDictionary
inManagedObjectContext:context
withError:nil];
}
+ (instancetype)findOrCreateObjectWithEntityName:(NSString *)entityName
byKeyObjectDictionary:(NSDictionary *)keyObjectDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
withError:(NSError *__autoreleasing *)error
{
NSArray *fetchedObjects = [self findObjectsWithEntityName:entityName
byKeyObjectDictionary:keyObjectDictionary
inManagedObjectContext:context withError:error];
NSManagedObject *managedObject;
if (fetchedObjects && fetchedObjects.count > 0) {
managedObject = [fetchedObjects firstObject];
} else {
managedObject = [self createObjectWithEntityName:entityName inManagedObjectContext:context];
if (keyObjectDictionary) {
[keyObjectDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSManagedObjectID class]]) {
[managedObject setValue:[context objectWithID:obj] forKey:key];
} else {
[managedObject setValue:obj forKey:key];
}
}];
}
}
return managedObject;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment