Crash on [NSKeyedArchiver archivedDataWithRootObject:self.data]

ios, locking, multithreading, objective-c

Solution

The problem was due to enter a resource (self.data) for several different thread. My solution (which works) was this:

@property (nonatomic, assign) dispatch_queue_t persistanceQueue;

On the init:

self.persistanceQueue = dispatch_queue_create("com.myApp.savingQueue", NULL);

For the sync method:

- (void) synchronize
{
    dispatch_sync(self.persistanceQueue, ^(void) {
        NSData *encryptedData = [NSKeyedArchiver archivedDataWithRootObject:self.data];
        BOOL success = [NSKeyedArchiver archiveRootObject:encryptedData toFile:[self filename]];

        if (!success)
        {
            // we lost some data :(
            NSLog(@"Failed to synchronize to file %@", [self filename]);
        }
    });
}

For getters:

- (id)objectForKey:(NSString *)defaultName {
    __block id returnValue = nil;
    dispatch_sync(self.persistanceQueue, ^{
        returnValue = self.data[defaultName];
    });

    return returnValue;
}

And for Setters:

- (void)setObject:(id)value forKey:(NSString *)defaultName
{
    dispatch_sync(self.persistanceQueue, ^{
        if (value != nil)
            self.data[defaultName] = value;
        else
            NSLog(@"Failed to save %@", defaultName);
    });
}

Problem

I have this method with a crash on `[NSKeyedArchiver archivedDataWithRootObject:self.data]`: ``` - (void) synchronize { @synchronized (self.data) { NSData *encryptedData = [[NSKeyedArchiver archivedDataWithRootObject:self.data] NL_AES256EncryptWithKey:userKey]; //La ça crash BOOL success = [NSKeyedArchiver archiveRootObject:encryptedData toFile:[self filename]]; if (!success) { // we lost some data :( NSLog(@"Failed to synchronize to file %@", [self filename]); } } } ``` The problem is that all access to the object method (getter/setter) are protected with `@synchronized(self.data)` and this property is private. Any idea? EDIT: The crash log is explicit: ``` *** Collection <__NSArrayM: 0x1756a800> was mutated while being enumerated. 0 CoreFoundation 0x2e95becb __exceptionPreprocess + 131 1 libobjc.A.dylib 0x390f2ce7 objc_exception_throw + 39 2 CoreFoundation 0x2e95b9b9 -[NSException name] + 1 3 Foundation 0x2f2dd647 -[NSKeyedArchiver _encodeArrayOfObjects:forKey:] + 383 4 Foundation 0x2f2ddc2d -[NSArray(NSArray) encodeWithCoder:] + 189 5 Foundation 0x2f2dc479 _encodeObject + 1061 6 Foundation 0x2f2dd657 -[NSKeyedArchiver _encodeArrayOfObjects:forKey:] + 399 7 Foundation 0x2f2dd329 -[NSDictionary(NSDictionary) encodeWithCoder:] + 921 8 Foundation 0x2f2dc479 _encodeObject + 1061 9 Foundation 0x2f2e2899 +[NSKeyedArchiver archivedDataWithRootObject:] + 157 ``` But I don't know how to proceed to prevent the crash.

Original source