2014-07-11 6 views
5

나는 [NSKeyedArchiver archivedDataWithRootObject:self.data]에 충돌이 방법이 있습니다충돌은

문제는 개체 메서드 (게터/세터)에 대한 모든 액세스가 @synchronized(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]); 
     } 
    } 
} 

및 이 속성은 비공개입니다.

아이디어가 있으십니까?

편집 : 충돌 로그는 명시 적입니다 :

*** 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 

하지만 충돌을 방지하기 위해 진행하는 방법을 모르겠어요.

+0

self.data를 변경하려면 다른 스레드를 사용하고 있습니까? – jailani

+0

코드의 어느 위치에서나 열거 형 API를 사용하고 있습니까? self.data가 Mutable 데이터 유형이고 Enumeration API와 함께 사용하는 경우이 종류의 충돌이 발생합니다. 한 번에 두 가지를 동시에 사용할 수는 없습니다. – DShah

+0

@ jailani : 예 :이 클래스는 프로젝트에서 데이터를 저장하는 데 사용되는 도구 클래스입니다. 그러나이 클래스의 모든 메서드는 모든 코드에서 다른 스레드에서 호출됩니다. – NiClou

답변

3

문제는 여러 스레드에 대한 자원 (self.data)을 입력했기 때문에 발생했습니다. 게터 용

- (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]); 
     } 
    }); 
} 

:

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

    return returnValue; 
} 

동기화 방법

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

: 초기화에

@property (nonatomic, assign) dispatch_queue_t persistanceQueue; 

: 내 용액 (작동 함)이 있었다 그리고 세터 :

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