崩溃[NSKeyedArchiver archivedDataWithRootObject:self.data]

Nik*_*Loy 5 multithreading locking objective-c ios

我有这个方法崩溃[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]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是对对象方法(getter/setter)的所有访问都受到保护,@synchronized(self.data)并且此属性是私有的.

任何的想法?

编辑:崩溃日志是明确的:

*** 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
Run Code Online (Sandbox Code Playgroud)

但我不知道如何防止崩溃.

Nik*_*Loy 5

问题是由于要为几个不同的线程输入资源(self.data)。我的解决方案(有效)是这样的:

@property (nonatomic, assign) dispatch_queue_t persistanceQueue;
Run Code Online (Sandbox Code Playgroud)

在初始化上:

self.persistanceQueue = dispatch_queue_create("com.myApp.savingQueue", NULL);
Run Code Online (Sandbox Code Playgroud)

对于同步方法:

- (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]);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

对于吸气剂:

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

    return returnValue;
}
Run Code Online (Sandbox Code Playgroud)

对于二传手:

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