forked from QueryKit/QueryKit
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathQKQuerySet.m
More file actions
314 lines (228 loc) · 9.56 KB
/
Copy pathQKQuerySet.m
File metadata and controls
314 lines (228 loc) · 9.56 KB
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
//
// QKQuerySet.m
// QueryKit
//
// Created by Kyle Fuller on 30/04/2013.
//
//
#import "QKQuerySet.h"
NSString * const QKQuerySetErrorDomain = @"QKQuerySetErrorDomain";
@interface QKQuerySet ()
@property (nonatomic, strong) NSArray *resultsCache;
@end
@implementation QKQuerySet
#pragma mark - Creation
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription {
return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:nil sortDescriptors:nil range:NSMakeRange(NSNotFound, NSNotFound)];
}
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext fetchRequest:(NSFetchRequest *)fetchRequest {
NSParameterAssert(fetchRequest != nil);
NSEntityDescription *entityDescription = [fetchRequest entity];
NSPredicate *predicate = [fetchRequest predicate];
NSArray *sortDescriptors = [fetchRequest sortDescriptors];
return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(NSNotFound, NSNotFound)];
}
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription predicate:(NSPredicate *)predicate sortDescriptors:(NSArray *)sortDescriptors range:(NSRange)range {
NSParameterAssert(managedObjectContext != nil);
NSParameterAssert(entityDescription != nil);
if (self = [super init]) {
_managedObjectContext = managedObjectContext;
_entityDescription = entityDescription;
_predicate = [predicate copy];
_sortDescriptors = sortDescriptors? [sortDescriptors copy] : @[];
_range = range;
}
return self;
}
- (instancetype)init {
NSString *reason = [NSString stringWithFormat:@"%@ Failed to call designated initializer.", NSStringFromClass([self class])];
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:nil];
}
#pragma mark - Equality
- (NSUInteger)hash {
return [self.managedObjectContext hash];
}
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if ([object isKindOfClass:[QKQuerySet class]] == NO) {
return NO;
}
return [self isEqualToQuerySet:object];
}
- (BOOL)isEqualToQuerySet:(QKQuerySet *)queryset {
return (
[self.managedObjectContext isEqual:[queryset managedObjectContext]] &&
[self.entityDescription isEqual:[queryset entityDescription]] &&
[self.predicate isEqual:[queryset predicate]] &&
[self.sortDescriptors isEqual:[queryset sortDescriptors]] &&
NSEqualRanges(self.range, queryset.range)
);
}
#pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone {
return [[[self class] allocWithZone:zone] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:self.predicate sortDescriptors:self.sortDescriptors range:self.range];
}
#pragma mark - NSFastEnumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len {
if (_resultsCache == nil) {
[self array:nil];
}
return [_resultsCache countByEnumeratingWithState:state objects:buffer count:len];
}
#pragma mark - Fetching
- (NSFetchRequest *)fetchRequest {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:_entityDescription];
[fetchRequest setPredicate:self.predicate];
[fetchRequest setSortDescriptors:self.sortDescriptors];
if (self.range.location != NSNotFound) {
fetchRequest.fetchOffset = self.range.location;
fetchRequest.fetchLimit = self.range.length;
}
return fetchRequest;
}
- (NSUInteger)count:(NSError **)error {
NSUInteger count = 0;
if (_resultsCache) {
count = [_resultsCache count];
} else {
NSFetchRequest *fetchRequest = [self fetchRequest];
count = [self.managedObjectContext countForFetchRequest:fetchRequest error:error];
}
return count;
}
- (NSArray *)array:(NSError **)error {
if (_resultsCache == nil) {
_resultsCache = [self.managedObjectContext executeFetchRequest:[self fetchRequest] error:error];
}
return _resultsCache;
}
- (NSSet *)set:(NSError **)error {
NSArray *array = [self array:error];
NSSet *set;
if (array != nil) {
set = [NSSet setWithArray:array];
}
return set;
}
- (NSOrderedSet *)orderedSet:(NSError **)error {
NSArray *array = [self array:error];
NSOrderedSet *orderedSet;
if (array != nil) {
orderedSet = [NSOrderedSet orderedSetWithArray:array];
}
return orderedSet;
}
- (BOOL)enumerateObjects:(void (^)(NSManagedObject *object, NSUInteger index, BOOL *stop))block error:(NSError **)error {
NSArray *array = [self array:error];
if (array != nil) {
[array enumerateObjectsUsingBlock:block];
}
return array != nil;
}
- (BOOL)each:(void (^)(NSManagedObject *managedObject))block error:(NSError **)error {
NSArray *array = [self array:error];
if (array != nil) {
for (NSManagedObject *managedObject in array) {
block(managedObject);
}
}
return array != nil;
}
#pragma mark - Deletion
- (NSUInteger)deleteObjects:(NSError **)error {
NSArray *array = [self array:error];
NSUInteger count = 0;
if (array != nil) {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
for (NSManagedObject *managedObject in array) {
[managedObjectContext deleteObject:managedObject];
++count;
}
}
return count;
}
@end
@implementation QKQuerySet (Sorting)
- (instancetype)orderBy:(NSArray *)sortDescriptors {
return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range];
}
- (instancetype)reverse {
NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithCapacity:[_sortDescriptors count]];
for (NSSortDescriptor *sortDescriptor in _sortDescriptors) {
[sortDescriptors addObject:[sortDescriptor reversedSortDescriptor]];
}
return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range];
}
@end
@implementation QKQuerySet (Filtering)
- (instancetype)exclude:(NSPredicate *)predicate {
predicate = [[NSCompoundPredicate alloc] initWithType:NSNotPredicateType subpredicates:@[predicate]];
if (_predicate) {
predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]];
}
return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range];
}
- (instancetype)filter:(NSPredicate *)predicate {
if (_predicate) {
predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]];
}
return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range];
}
@end
@implementation QKQuerySet (SingleObject)
- (NSManagedObject *)object:(NSError **)error {
NSManagedObject *managedObject;
NSArray *array;
if (_resultsCache) {
array = _resultsCache;
} else {
NSFetchRequest *fetchRequest = [self fetchRequest];
fetchRequest.fetchBatchSize = 1; // Only request one
array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error];
}
NSUInteger count = [array count];
if (count == 1) {
managedObject = [array firstObject];
} else if ((count > 1) && error != nil) {
*error = [NSError errorWithDomain:QKQuerySetErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Find object in fetch request failed, should only result in a single result.",
}];
}
return managedObject;
}
- (NSManagedObject *)firstObject:(NSError **)error {
NSManagedObject *managedObject;
if (_resultsCache) {
managedObject = [_resultsCache firstObject];
} else {
NSFetchRequest *fetchRequest = [self fetchRequest];
[fetchRequest setFetchLimit:1];
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error];
managedObject = [array firstObject];
}
return managedObject;
}
- (NSManagedObject *)lastObject:(NSError **)error {
NSManagedObject *managedObject;
if (_resultsCache) {
managedObject = [_resultsCache lastObject];
} else {
NSFetchRequest *fetchRequest = [self fetchRequest];
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error];
managedObject = [array lastObject];
}
return managedObject;
}
@end
@implementation NSManagedObject (QKQuerySet)
+ (NSString *)entityName {
return NSStringFromClass([self class]);
}
+ (QKQuerySet *)querySetWithManagedObjectContext:(NSManagedObjectContext *)context {
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:context];
return [[QKQuerySet alloc] initWithManagedObjectContext:context entityDescription:entityDescription];
}
@end