mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-02 17:57:22 +08:00
190 lines
6.5 KiB
Objective-C
190 lines
6.5 KiB
Objective-C
//
|
|
// RKManagedObjectStore.m
|
|
// RestKit
|
|
//
|
|
// Created by Blake Watters on 9/22/09.
|
|
// Copyright 2009 Two Toasters. All rights reserved.
|
|
//
|
|
|
|
#import "RKManagedObjectStore.h"
|
|
#import <UIKit/UIKit.h>
|
|
|
|
NSString* const RKManagedObjectStoreDidFailSaveNotification = @"RKManagedObjectStoreDidFailSaveNotification";
|
|
static NSString* const kRKManagedObjectContextKey = @"RKManagedObjectContext";
|
|
|
|
@interface RKManagedObjectStore (Private)
|
|
- (void)createPersistentStoreCoordinator;
|
|
- (NSString *)applicationDocumentsDirectory;
|
|
- (NSManagedObjectContext*)newManagedObjectContext;
|
|
@end
|
|
|
|
@implementation RKManagedObjectStore
|
|
|
|
@synthesize storeFilename = _storeFilename;
|
|
@synthesize managedObjectModel = _managedObjectModel;
|
|
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
|
|
@synthesize managedObjectContext = _managedObjectContext;
|
|
@synthesize managedObjectCache = _managedObjectCache;
|
|
|
|
- (id)initWithStoreFilename:(NSString*)storeFilename {
|
|
if (self = [self init]) {
|
|
_storeFilename = [storeFilename retain];
|
|
_managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
|
|
[self createPersistentStoreCoordinator];
|
|
_managedObjectContext = [self newManagedObjectContext];
|
|
_managedObjectCache = nil;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
[_storeFilename release];
|
|
_storeFilename = nil;
|
|
[_managedObjectContext release];
|
|
_managedObjectContext = nil;
|
|
[_managedObjectModel release];
|
|
_managedObjectModel = nil;
|
|
[_persistentStoreCoordinator release];
|
|
_persistentStoreCoordinator = nil;
|
|
[_managedObjectCache release];
|
|
_managedObjectCache = nil;
|
|
[super dealloc];
|
|
}
|
|
|
|
/**
|
|
Performs the save action for the application, which is to send the save:
|
|
message to the application's managed object context.
|
|
*/
|
|
- (NSError*)save {
|
|
NSError *error = nil;
|
|
@try {
|
|
[[self managedObjectContext] save:&error];
|
|
}
|
|
@catch (NSException* e) {
|
|
// TODO: This needs to be reworked into a delegation pattern
|
|
NSString* errorMessage = [NSString stringWithFormat:@"An unrecoverable error was encountered while trying to save the database: %@", [e reason]];
|
|
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Ruh roh.", nil)
|
|
message:errorMessage
|
|
delegate:nil
|
|
cancelButtonTitle:NSLocalizedString(@"OK", nil)
|
|
otherButtonTitles:nil];
|
|
[alert show];
|
|
[alert release];
|
|
}
|
|
@finally {
|
|
if (error) {
|
|
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:error forKey:@"error"];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RKManagedObjectStoreDidFailSaveNotification object:self userInfo:userInfo];
|
|
}
|
|
return error;
|
|
}
|
|
}
|
|
|
|
- (NSManagedObjectContext*)newManagedObjectContext {
|
|
NSManagedObjectContext* managedObjectContext = [[NSManagedObjectContext alloc] init];
|
|
[managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
|
|
[managedObjectContext setUndoManager:nil];
|
|
[managedObjectContext setMergePolicy:NSOverwriteMergePolicy];
|
|
|
|
return managedObjectContext;
|
|
}
|
|
|
|
- (void)createPersistentStoreCoordinator {
|
|
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent:_storeFilename]];
|
|
|
|
NSError *error;
|
|
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_managedObjectModel];
|
|
|
|
// Allow inferred migration from the original version of the application.
|
|
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
|
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
|
|
|
|
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
|
|
// TODO: Needs to be handled with delegation... Allow the application to handle migration.
|
|
}
|
|
}
|
|
|
|
- (void)deletePersistantStore {
|
|
NSURL* storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent:_storeFilename]];
|
|
NSError* error = nil;
|
|
NSLog(@"Error removing persistant store: %@", [error localizedDescription]);
|
|
if (error) {
|
|
//Handle error
|
|
}
|
|
error = nil;
|
|
[[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:&error];
|
|
if (error) {
|
|
//Handle error
|
|
}
|
|
|
|
[_persistentStoreCoordinator release];
|
|
[_managedObjectContext release];
|
|
|
|
[self createPersistentStoreCoordinator];
|
|
_managedObjectContext = [self newManagedObjectContext];
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Override managedObjectContext getter to ensure we return a separate context
|
|
* for each NSThread.
|
|
*
|
|
*/
|
|
-(NSManagedObjectContext*)managedObjectContext {
|
|
if ([NSThread isMainThread]) {
|
|
return _managedObjectContext;
|
|
} else {
|
|
NSMutableDictionary* threadDictionary = [[NSThread currentThread] threadDictionary];
|
|
NSManagedObjectContext* backgroundThreadContext = [threadDictionary objectForKey:kRKManagedObjectContextKey];
|
|
if (!backgroundThreadContext) {
|
|
backgroundThreadContext = [self newManagedObjectContext];
|
|
[threadDictionary setObject:backgroundThreadContext forKey:kRKManagedObjectContextKey];
|
|
[backgroundThreadContext release];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:)
|
|
name:NSManagedObjectContextDidSaveNotification
|
|
object:backgroundThreadContext];
|
|
}
|
|
return backgroundThreadContext;
|
|
}
|
|
}
|
|
|
|
- (void)mergeChanges:(NSNotification *)notification {
|
|
// Merge changes into the main context on the main thread
|
|
[_managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
|
|
withObject:notification
|
|
waitUntilDone:YES];
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Helpers
|
|
|
|
/**
|
|
Returns the path to the application's documents directory.
|
|
*/
|
|
- (NSString *)applicationDocumentsDirectory {
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
|
|
return basePath;
|
|
}
|
|
|
|
- (NSManagedObject*)objectWithID:(NSManagedObjectID*)objectID {
|
|
return [self.managedObjectContext objectWithID:objectID];
|
|
}
|
|
|
|
- (NSArray*)objectsWithIDs:(NSArray*)objectIDs {
|
|
NSMutableArray* objects = [[NSMutableArray alloc] init];
|
|
for (NSManagedObjectID* objectID in objectIDs) {
|
|
[objects addObject:[self.managedObjectContext objectWithID:objectID]];
|
|
}
|
|
NSArray* objectArray = [NSArray arrayWithArray:objects];
|
|
[objects release];
|
|
|
|
return objectArray;
|
|
}
|
|
|
|
@end
|