Skip to content
This repository
Browse code

Fix issues with refetching results using visitation

  • Loading branch information...
commit 9a128b678cad23c5d302d1110bf4ccd72ce3e9ac 1 parent 312b382
Blake Watters authored December 30, 2012
65  Code/Network/RKManagedObjectRequestOperation.m
@@ -87,6 +87,8 @@ - (id)initWithResponseDescriptors:(NSArray *)responseDescriptors
87 87
         self.visitations = [NSMutableArray array];
88 88
         
89 89
         for (RKResponseDescriptor *responseDescriptor in responseDescriptors) {
  90
+            [self.visitationStack removeAllObjects];
  91
+            [self.lowValues removeAllObjects];
90 92
             [self visitMapping:responseDescriptor.mapping atKeyPath:responseDescriptor.keyPath];
91 93
         }
92 94
     }
@@ -240,10 +242,10 @@ static void RKAddObjectsInGraphWithCyclicKeyPathsToMutableSet(id graph, NSSet *c
240 242
  For example, given a set containing: 'this', 'this.that', 'another.one.test', 'another.two.test', 'another.one.test.nested'
241 243
  would return: 'this, 'another.one', 'another.two'
242 244
  */
243  
-NSSet *RKSetByRemovingSubkeypathsFromSet(NSSet *setOfKeyPaths);
244  
-NSSet *RKSetByRemovingSubkeypathsFromSet(NSSet *setOfKeyPaths)
  245
+NSOrderedSet *RKSetByRemovingSubkeypathsFromSet(NSSet *setOfKeyPaths);
  246
+NSOrderedSet *RKSetByRemovingSubkeypathsFromSet(NSSet *setOfKeyPaths)
245 247
 {
246  
-    return [setOfKeyPaths objectsPassingTest:^BOOL(NSString *keyPath, BOOL *stop) {
  248
+    NSSet *prunedSet = [setOfKeyPaths objectsPassingTest:^BOOL(NSString *keyPath, BOOL *stop) {
247 249
         if ([keyPath isEqual:[NSNull null]]) return YES; // Special case the root key path
248 250
         NSArray *keyPathComponents = [keyPath componentsSeparatedByString:@"."];
249 251
         NSMutableSet *parentKeyPaths = [NSMutableSet set];
@@ -255,6 +257,12 @@ static void RKAddObjectsInGraphWithCyclicKeyPathsToMutableSet(id graph, NSSet *c
255 257
         }
256 258
         return YES;
257 259
     }];
  260
+    NSMutableOrderedSet *orderedSet = [NSMutableOrderedSet orderedSetWithSet:prunedSet];
  261
+    if ([orderedSet containsObject:[NSNull null]]) {
  262
+        [orderedSet removeObject:[NSNull null]];
  263
+        [orderedSet setObject:[NSNull null] atIndex:0];
  264
+    }
  265
+    return orderedSet;
258 266
 }
259 267
 
260 268
 static void RKSetMappedValueForKeyPathInDictionary(id value, id rootKey, NSString *keyPath, NSMutableDictionary *dictionary)
@@ -288,17 +296,33 @@ static void RKSetMappedValueForKeyPathInDictionary(id value, id rootKey, NSStrin
288 296
 // Finds the key paths for all entity mappings in the graph whose parent objects are not other managed objects
289 297
 static NSDictionary *RKDictionaryFromDictionaryWithManagedObjectsInVisitationsRefetchedInContext(NSDictionary *dictionaryOfManagedObjects, NSArray *visitations, NSManagedObjectContext *managedObjectContext)
290 298
 {
291  
-    if (! [dictionaryOfManagedObjects count]) return dictionaryOfManagedObjects;    
  299
+    if (! [dictionaryOfManagedObjects count]) return dictionaryOfManagedObjects;
292 300
     NSMutableDictionary *newDictionary = [dictionaryOfManagedObjects mutableCopy];
293 301
     [managedObjectContext performBlockAndWait:^{
294  
-        NSArray *rootKeys = [visitations valueForKey:@"rootKey"];
  302
+        NSSet *rootKeys = [NSSet setWithArray:[visitations valueForKey:@"rootKey"]];
295 303
         for (id rootKey in rootKeys) {
296  
-            NSSet *keyPaths = [visitations valueForKey:@"keyPath"];
297  
-            // If keyPaths contains null, then the root object is a managed object and we only need to refetch it
298  
-            NSSet *nonNestedKeyPaths = ([keyPaths containsObject:[NSNull null]]) ? [NSSet setWithObject:[NSNull null]] : RKSetByRemovingSubkeypathsFromSet(keyPaths);
  304
+            NSSet *keyPaths = [NSSet setWithArray:[visitations valueForKey:@"keyPath"]];
  305
+            NSOrderedSet *nonNestedKeyPaths = RKSetByRemovingSubkeypathsFromSet(keyPaths);
299 306
             
300 307
             NSDictionary *mappingResultsAtRootKey = [dictionaryOfManagedObjects objectForKey:rootKey];
301 308
             for (NSString *keyPath in nonNestedKeyPaths) {
  309
+                __block BOOL refetched = NO;
  310
+                
  311
+                if (! [keyPath isEqual:[NSNull null]]) {
  312
+                    if ([mappingResultsAtRootKey conformsToProtocol:@protocol(NSFastEnumeration)]) {
  313
+                        // This is a collection
  314
+                        BOOL respondsToSelector = YES;
  315
+                        for (id object in mappingResultsAtRootKey) {
  316
+                            if (! [object respondsToSelector:NSSelectorFromString(keyPath)]) respondsToSelector = NO;
  317
+                        }
  318
+                        
  319
+                        if (! respondsToSelector) continue;
  320
+                    } else {
  321
+                        if (! [mappingResultsAtRootKey respondsToSelector:NSSelectorFromString(keyPath)]) {
  322
+                            continue;
  323
+                        }
  324
+                    }
  325
+                }
302 326
                 id value = [keyPath isEqual:[NSNull null]] ? mappingResultsAtRootKey : [mappingResultsAtRootKey valueForKeyPath:keyPath];
303 327
                 if (! value) {
304 328
                     continue;
@@ -306,7 +330,10 @@ static void RKSetMappedValueForKeyPathInDictionary(id value, id rootKey, NSStrin
306 330
                     BOOL isMutable = [value isKindOfClass:[NSMutableArray class]];
307 331
                     NSMutableArray *newValue = [[NSMutableArray alloc] initWithCapacity:[value count]];
308 332
                     for (__strong id object in value) {
309  
-                        if ([object isKindOfClass:[NSManagedObject class]]) object = RKRefetchManagedObjectInContext(object, managedObjectContext);                    
  333
+                        if ([object isKindOfClass:[NSManagedObject class]]) {
  334
+                            object = RKRefetchManagedObjectInContext(object, managedObjectContext);
  335
+                            refetched = YES;
  336
+                        }
310 337
                         if (object) [newValue addObject:object];
311 338
                     }
312 339
                     value = (isMutable) ? newValue : [newValue copy];
@@ -314,7 +341,10 @@ static void RKSetMappedValueForKeyPathInDictionary(id value, id rootKey, NSStrin
314 341
                     BOOL isMutable = [value isKindOfClass:[NSMutableSet class]];
315 342
                     NSMutableSet *newValue = [[NSMutableSet alloc] initWithCapacity:[value count]];
316 343
                     for (__strong id object in value) {
317  
-                        if ([object isKindOfClass:[NSManagedObject class]]) object = RKRefetchManagedObjectInContext(object, managedObjectContext);                    
  344
+                        if ([object isKindOfClass:[NSManagedObject class]]) {
  345
+                            object = RKRefetchManagedObjectInContext(object, managedObjectContext);
  346
+                            refetched = YES;
  347
+                        }
318 348
                         if (object) [newValue addObject:object];
319 349
                     }
320 350
                     value = (isMutable) ? newValue : [newValue copy];
@@ -322,15 +352,26 @@ static void RKSetMappedValueForKeyPathInDictionary(id value, id rootKey, NSStrin
322 352
                     BOOL isMutable = [value isKindOfClass:[NSMutableOrderedSet class]];
323 353
                     NSMutableOrderedSet *newValue = [NSMutableOrderedSet orderedSet];
324 354
                     [(NSOrderedSet *)value enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) {
325  
-                        if ([object isKindOfClass:[NSManagedObject class]]) object = RKRefetchManagedObjectInContext(object, managedObjectContext);
  355
+                        if ([object isKindOfClass:[NSManagedObject class]]) {
  356
+                            object = RKRefetchManagedObjectInContext(object, managedObjectContext);
  357
+                            refetched = YES;
  358
+                        }
326 359
                         if (object) [newValue setObject:object atIndex:index];
327 360
                     }];
328 361
                     value = (isMutable) ? newValue : [newValue copy];
329 362
                 } else if ([value isKindOfClass:[NSManagedObject class]]) {
330 363
                     value = RKRefetchManagedObjectInContext(value, managedObjectContext);
  364
+                    refetched = YES;
331 365
                 }
332 366
                 
333  
-                if (value) RKSetMappedValueForKeyPathInDictionary(value, rootKey, keyPath, newDictionary);
  367
+                if (value) {
  368
+                    RKSetMappedValueForKeyPathInDictionary(value, rootKey, keyPath, newDictionary);
  369
+                    
  370
+                    // If we have refetched the root object, then we are done
  371
+                    if (keyPath == [NSNull null] && refetched) {
  372
+                        break;
  373
+                    }
  374
+                }
334 375
             }
335 376
         }
336 377
     }];

0 notes on commit 9a128b6

Please sign in to comment.
Something went wrong with that request. Please try again.