Besi
Besi

Reputation: 22939

Crash with RestKit when issuing multiple requests in quick succession

I have a button with two buttons which start the download of some data from a web server with RestKit.

Now if the user taps the two buttons repeatedly in quick succession my app crashes and produces the crash log below.

I initiate my requests like so:

-(void)loadDataAtPath:(NSString *)path completion:(ResultArrayBlock)completionBlock failed:(ResultFailedBlock)failedBlock
{
    RKObjectMapping *groupMapping = [Group mapping];

    [self.objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups.group"];
    [self.objectManager.mappingProvider setObjectMapping:groupMapping forKeyPath:path];  

    [self.objectManager loadObjectsAtResourcePath:path usingBlock:^(RKObjectLoader *loader) {
        loader.onDidLoadObjects = ^(NSArray *array){

            // Do the reverse mapping of the group
            for (Group *c in array) {
                for(Person *p in c.persons){
                    p.group = c;
                }
            }

            completionBlock(array);

        };
        loader.onDidFailWithError = failedBlock;
    }];
}

I first thought that the problem was the for-loop where I do some after-mapping setup of my data, but the problem still persists even when commenting the for-loop.

Curiously this problem does not occur in the simulator even when I switch on the Network Link Conditioner.prefpane

The crash

When I debug this on the device I get the following on the console.

[PLCrashReport] Terminated stack walking early: Corrupted frame
[PLCrashReport] Terminated stack walking early: Corrupted frame

The crash log looks like this:

Application Specific Information:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFDictionary: 0x3c14a0> was mutated while being enumerated.'

Last Exception Backtrace:
0   CoreFoundation                      0x3734e88f __exceptionPreprocess + 162
1   libobjc.A.dylib                     0x35053259 objc_exception_throw + 32
2   CoreFoundation                      0x3734e3b3 __NSFastEnumerationMutationHandler + 162
3   MyApp                               0x0008f5bf -[RKObjectMapper performKeyPathMappingUsingMappingDictionary:] + 407
4   MyApp                               0x0008fa45 -[RKObjectMapper performMapping] + 673
5   MyApp                               0x0008ac7d -[RKObjectLoader mapResponseWithMappingProvider:toObject:inContext:error:] + 1045
6   MyApp                               0x0008b04f -[RKObjectLoader performMapping:] + 575
7   MyApp                               0x0008b22b __47-[RKObjectLoader performMappingInDispatchQueue]_block_invoke_0 + 247
8   libdispatch.dylib                   0x3046ec59 _dispatch_call_block_and_release + 12
9   libdispatch.dylib                   0x30479cab _dispatch_queue_drain + 274
10  libdispatch.dylib                   0x30479b19 _dispatch_queue_invoke$VARIANT$up + 36
11  libdispatch.dylib                   0x3047a78b _dispatch_worker_thread2 + 214
12  libsystem_c.dylib                   0x33bbddfb _pthread_wqthread + 294
13  libsystem_c.dylib                   0x33bbdcd0 start_wqthread + 8

Upvotes: 1

Views: 698

Answers (1)

Paul de Lange
Paul de Lange

Reputation: 10633

As @PhillipMills suggested, you can easily see the answer when you look inside performKeyPathMappingUsingMappingDictionary. Your problem is repeatedly setting the mapping with these lines:

[self.objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups.group"];
[self.objectManager.mappingProvider setObjectMapping:groupMapping forKeyPath:path];  

If you call this line while the response is being mapping it triggers the error because you are changing the same dictionary it is trying to fast enumerate over.

Normally, you would set the mapping somewhere in the initial configuration and NOT each time like this.

Upvotes: 3

Related Questions