-
Notifications
You must be signed in to change notification settings - Fork 0
/
AGTCoreDataStack.m
executable file
·205 lines (151 loc) · 6.41 KB
/
AGTCoreDataStack.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//
// AGTCoreDataStack.m
//
// Created by Fernando Rodríguez Romero on 1/24/13.
// Copyright (c) 2013 Agbo. All rights reserved.
//
#import <CoreData/CoreData.h>
#import "AGTCoreDataStack.h"
@interface AGTCoreDataStack ()
@property (strong, nonatomic, readonly) NSManagedObjectModel *model;
@property (strong, nonatomic, readonly) NSPersistentStoreCoordinator *storeCoordinator;
@property (strong, nonatomic) NSURL *modelURL;
@property (strong, nonatomic) NSURL *dbURL;
@end
@implementation AGTCoreDataStack
#pragma mark - Properties
// When using a readonly property with a custom getter, auto-synthesize
// is disabled.
// See http://www.cocoaosx.com/2012/12/04/auto-synthesize-property-reglas-excepciones/
// (in Spanish)
@synthesize model=_model;
@synthesize storeCoordinator=_storeCoordinator;
@synthesize context=_context;
-(NSManagedObjectContext *)context{
if (_context == nil){
_context = [[NSManagedObjectContext alloc] init];
_context.persistentStoreCoordinator = self.storeCoordinator;
}
return _context;
}
-(NSPersistentStoreCoordinator *) storeCoordinator{
if (_storeCoordinator == nil) {
_storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model];
NSError *err = nil;
if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.dbURL
options:nil
error:&err ]) {
// Something went really wrong...
// Send a notification and return nil
NSNotification *note = [NSNotification
notificationWithName:[AGTCoreDataStack persistentStoreCoordinatorErrorNotificationName]
object:self
userInfo:@{@"error" : err}];
[[NSNotificationCenter defaultCenter] postNotification:note];
NSLog(@"Error while adding a Store: %@", err);
return nil;
}
}
return _storeCoordinator;
}
-(NSManagedObjectModel *) model{
if (_model == nil) {
_model = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL];
}
return _model;
}
#pragma mark - Class Methods
+(NSString *) persistentStoreCoordinatorErrorNotificationName{
return @"persistentStoreCoordinatorErrorNotificationName";
}
// Returns the URL to the application's Documents directory.
+ (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
+(AGTCoreDataStack *) coreDataStackWithModelName:(NSString *)aModelName
databaseFilename:(NSString*) aDBName{
NSURL *url = nil;
if (aDBName) {
url = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:aDBName];
}else{
url = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:aModelName];
}
return [self coreDataStackWithModelName:aModelName
databaseURL:url];
}
+(AGTCoreDataStack *) coreDataStackWithModelName:(NSString *)aModelName{
return [self coreDataStackWithModelName:aModelName
databaseFilename:nil];
}
+(AGTCoreDataStack *) coreDataStackWithModelName:(NSString *)aModelName
databaseURL:(NSURL*) aDBURL{
return [[self alloc] initWithModelName: aModelName databaseURL:aDBURL];
}
#pragma mark - Init
-(id) initWithModelName:(NSString *)aModelName
databaseURL:(NSURL*) aDBURL{
if (self = [super init]) {
self.modelURL = [[NSBundle mainBundle] URLForResource:aModelName
withExtension:@"momd"];
self.dbURL = aDBURL;
}
return self;
}
#pragma mark - Others
-(void) zapAllData{
NSError *err = nil;
for (NSPersistentStore *store in self.storeCoordinator.persistentStores) {
if(![self.storeCoordinator removePersistentStore:store
error:&err]){
NSLog(@"Error while removing store %@ from store coordinator %@", store, self.storeCoordinator);
}
}
if (![[NSFileManager defaultManager] removeItemAtURL:self.dbURL
error:&err]) {
NSLog(@"Error removing %@: %@", self.dbURL, err);
}
// The Core Data stack does not like you removing the file under it. If you want to delete the file
// you should tear down the stack, delete the file and then reconstruct the stack.
// Part of the problem is that the stack keeps a cache of the data that is in the file. When you
// remove the file you don't have a way to clear that cache and you are then putting
// Core Data into an unknown and unstable state.
_context = nil;
_storeCoordinator = nil;
_context = [self context]; // this will rebuild the stack
}
-(void) saveWithErrorBlock: (void(^)(NSError *error))errorBlock{
NSError *err = nil;
// If a context is nil, saving it should also be considered an
// error, as being nil might be the result of a previous error
// while creating the db.
if (!_context) {
err = [NSError errorWithDomain:@"AGTCoreDataStack"
code:1
userInfo:@{NSLocalizedDescriptionKey :
@"Attempted to save a nil NSManagedObjectContext. This AGTCoreDataStack has no context - probably there was an earlier error trying to access the CoreData database file."}];
errorBlock(err);
}else if (self.context.hasChanges) {
if (![self.context save:&err]) {
if (errorBlock != nil) {
errorBlock(err);
}
}
}
}
-(NSArray *) executeFetchRequest:(NSFetchRequest *)req
errorBlock:(void(^)(NSError *error)) errorBlock{
NSError *err;
NSArray *res = [self.context executeFetchRequest:req
error:&err];
if (res == nil) {
// la cagamos
if (errorBlock != nil) {
errorBlock(err);
}
}
return res;
}
@end