Created
October 5, 2012 16:20
-
-
Save sixten/3840794 to your computer and use it in GitHub Desktop.
RKManagedObjectStore subclass that is configuration-aware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RDManagedObjectStore.h | |
// Capri | |
// | |
// Created by Sixten Otto on 4/17/12. | |
// Copyright (c) 2012 Results Direct. 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 <RestKit/CoreData.h> | |
@interface RDManagedObjectStore : RKManagedObjectStore | |
+ (RDManagedObjectStore*)objectStoreWithStoreFilename:(NSString *)storeFilename inDirectory:(NSString *)directory usingSeedDatabaseName:(NSString *)nilOrNameOfSeedDatabaseInMainBundle managedObjectModel:(NSManagedObjectModel*)nilOrManagedObjectModel configuration:(NSString *)nilOrModelConfiguration; | |
- (NSError *)addPersistentStoreForConfiguration:(NSString *)configuration withFilename:(NSString *)storeFilename inDirectory:(NSString *)directory; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RDManagedObjectStore.m | |
// Capri | |
// | |
// Created by Sixten Otto on 4/17/12. | |
// Copyright (c) 2012 Results Direct. 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 "RDManagedObjectStore.h" | |
#import <RestKit/RKDirectory.h> | |
#import <RestKit/RKSearchWordObserver.h> | |
@interface RKManagedObjectStore (Private) | |
- (void)createPersistentStoreCoordinator; | |
- (void)createStoreIfNecessaryUsingSeedDatabase:(NSString*)seedDatabase; | |
@end | |
@interface RDManagedObjectStore () | |
@property (nonatomic, strong, readwrite) NSString *storeFilename; | |
@property (nonatomic, strong, readwrite) NSString *pathToStoreFile; | |
@property (nonatomic, strong, readwrite) NSManagedObjectModel *managedObjectModel; | |
@property (nonatomic, strong, readwrite) NSPersistentStoreCoordinator *persistentStoreCoordinator; | |
@property (nonatomic, strong, readwrite) NSManagedObjectContext *primaryManagedObjectContext; | |
@property (copy, nonatomic) NSString *configuration; | |
- (id)initWithStoreFilename:(NSString *)storeFilename inDirectory:(NSString *)nilOrDirectoryPath usingSeedDatabaseName:(NSString *)nilOrNameOfSeedDatabaseInMainBundle managedObjectModel:(NSManagedObjectModel*)nilOrManagedObjectModel configuration:(NSString *)nilOrModelConfiguration; | |
- (NSError *)addPersistentStoreForConfiguration:(NSString *)configuration URL:(NSURL *)storeURL; | |
@end | |
@implementation RDManagedObjectStore | |
@synthesize storeFilename = rd_storeFilename; | |
@synthesize pathToStoreFile = rd_pathToStoreFile; | |
@synthesize managedObjectModel = rd_managedObjectModel; | |
@synthesize persistentStoreCoordinator = rd_persistentStoreCoordinator; | |
@synthesize primaryManagedObjectContext = rd_primaryManagedObjectContext; | |
@synthesize configuration = rd_configuration; | |
+ (RDManagedObjectStore*)objectStoreWithStoreFilename:(NSString *)storeFilename inDirectory:(NSString *)directory usingSeedDatabaseName:(NSString *)nilOrNameOfSeedDatabaseInMainBundle managedObjectModel:(NSManagedObjectModel*)nilOrManagedObjectModel configuration:(NSString *)nilOrModelConfiguration | |
{ | |
return [[self alloc] initWithStoreFilename:storeFilename inDirectory:directory usingSeedDatabaseName:nilOrNameOfSeedDatabaseInMainBundle managedObjectModel:nilOrManagedObjectModel configuration:nilOrModelConfiguration]; | |
} | |
- (id)initWithStoreFilename:(NSString *)storeFilename inDirectory:(NSString *)nilOrDirectoryPath usingSeedDatabaseName:(NSString *)nilOrNameOfSeedDatabaseInMainBundle managedObjectModel:(NSManagedObjectModel*)nilOrManagedObjectModel configuration:(NSString *)nilOrModelConfiguration { | |
self = [self init]; | |
if (self) { | |
self.storeFilename = storeFilename; | |
self.configuration = nilOrModelConfiguration; | |
if( nilOrDirectoryPath == nil ) { | |
nilOrDirectoryPath = [RKDirectory applicationDataDirectory]; | |
[RKDirectory ensureDirectoryExistsAtPath:nilOrDirectoryPath error:nil]; | |
} | |
else { | |
BOOL isDir; | |
NSAssert1([[NSFileManager defaultManager] fileExistsAtPath:nilOrDirectoryPath isDirectory:&isDir] && isDir == YES, @"Specified storage directory exists", nilOrDirectoryPath); | |
} | |
self.pathToStoreFile = [nilOrDirectoryPath stringByAppendingPathComponent:storeFilename]; | |
if (nilOrManagedObjectModel == nil) { | |
nilOrManagedObjectModel = [NSManagedObjectModel mergedModelFromBundles:[NSBundle allBundles]]; | |
} | |
NSMutableArray *allManagedObjectModels = [NSMutableArray arrayWithObject:nilOrManagedObjectModel]; | |
self.managedObjectModel = [NSManagedObjectModel modelByMergingModels:allManagedObjectModels]; | |
if (nilOrNameOfSeedDatabaseInMainBundle) { | |
[self createStoreIfNecessaryUsingSeedDatabase:nilOrNameOfSeedDatabaseInMainBundle]; | |
} | |
[self createPersistentStoreCoordinator]; | |
self.primaryManagedObjectContext = [self newManagedObjectContext]; | |
self.cacheStrategy = [RKInMemoryManagedObjectCache new]; | |
// Ensure there is a search word observer | |
[RKSearchWordObserver sharedObserver]; | |
// Hydrate the defaultObjectStore | |
if (! [[self class] defaultObjectStore] ) { | |
[[self class] setDefaultObjectStore:self]; | |
} | |
} | |
return self; | |
} | |
- (NSError *)addPersistentStoreForConfiguration:(NSString *)configuration URL:(NSURL *)storeURL | |
{ | |
NSPersistentStore* store = nil; | |
NSError *error = nil; | |
/* There seems to be trouble with combining configurations and migration. So | |
* do this in two steps: first, attach the store with NO configuration, | |
* but WITH migration options; then remove it and reattach WITH configuration, | |
* but NOT migration options. | |
* | |
* http://blog.atwam.com/blog/2012/05/11/multiple-persistent-stores-and-seed-data-with-core-data/ | |
* http://stackoverflow.com/questions/1774359/core-data-migration-error-message-model-does-not-contain-configuration-xyz | |
* | |
*/ | |
// migration pass | |
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: | |
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, | |
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, | |
nil]; | |
store = [self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]; | |
if( nil == store ) { | |
return error; | |
} | |
// remove store | |
if( ![self.persistentStoreCoordinator removePersistentStore:store error:&error] ) { | |
return error; | |
} | |
// reattach store | |
store = [self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:configuration URL:storeURL options:nil error:&error]; | |
if( nil == store ) { | |
return error; | |
} | |
return nil; | |
} | |
- (NSError *)addPersistentStoreForConfiguration:(NSString *)configuration withFilename:(NSString *)storeFilename inDirectory:(NSString *)directory | |
{ | |
NSURL* storeURL = [[NSURL fileURLWithPath:directory] URLByAppendingPathComponent:storeFilename]; | |
return [self addPersistentStoreForConfiguration:configuration URL:storeURL]; | |
} | |
- (void)createPersistentStoreCoordinator { | |
NSURL *storeUrl = [NSURL fileURLWithPath:self.pathToStoreFile]; | |
self.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; | |
NSError* error = [self addPersistentStoreForConfiguration:self.configuration URL:storeUrl]; | |
if( error ) { | |
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(managedObjectStore:didFailToCreatePersistentStoreCoordinatorWithError:)]) { | |
[self.delegate managedObjectStore:self didFailToCreatePersistentStoreCoordinatorWithError:error]; | |
} | |
else { | |
NSAssert(NO, @"Managed object store failed to create persistent store coordinator: %@", error); | |
} | |
} | |
} | |
- (NSManagedObjectContext *)newManagedObjectContext | |
{ | |
NSManagedObjectContext *managedObjectContext = nil; | |
if( [NSThread isMainThread] ) { | |
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; | |
} | |
else { | |
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; | |
} | |
[managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; | |
[managedObjectContext setUndoManager:nil]; | |
[managedObjectContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; | |
managedObjectContext.managedObjectStore = self; | |
return managedObjectContext; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// set up object store | |
RDManagedObjectStore* store = [RDManagedObjectStore | |
objectStoreWithStoreFilename:@"Server.sqlite" | |
inDirectory:appSupportPath | |
usingSeedDatabaseName:[self serverSeedDatabaseName] | |
managedObjectModel:managedObjectModel | |
configuration:@"Server"]; | |
store.delegate = self; | |
// don't back up the server-sourced content | |
[self setDontBackupOnURL:[[store.persistentStoreCoordinator.persistentStores lastObject] URL]]; | |
// separate storage for user-generated content | |
[store addPersistentStoreForConfiguration:@"UserGenerated" withFilename:@"UserGenerated.sqlite" inDirectory:appSupportPath]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment