2017-12-01 24 views
0

initton 메소드에 싱글 톤 클래스가 있는데, NSMutableArray을 설치하고 나중에 저장할 때이 크래시 로그가 무작위 적으로 크래시 될 수 있습니다. recordUploadCnt을 사용할 수 없습니다. , 그러나 어디서 잘못되었는지 알 수는 없습니다.NSUserDefaults setObject 크래시

NSString* const KEY_SENSOR_UPLOAD = @"recordUploadCnt"; 
    @property(nonatomic, strong) NSMutableArray* recordUploadCnt; 

- (id)init { 
    if (self = [super init]) { 
     NSMutableArray* cnt = [[NSUserDefaults standardUserDefaults] objectForKey:KEY_SENSOR_UPLOAD]; 
     self.recordUploadCnt = cnt ? [NSMutableArray arrayWithArray:cnt] : [NSMutableArray new]; 
    } 
    return self; 
} 

double currentTime = [[NSDate date] timeIntervalSince1970]; 
if ([self.recordUploadCnt count] < 6) { 
    [self.recordUploadCnt addObject:[NSString stringWithFormat:@"%f",currentTime]]; 
} else { 
    [self.recordUploadCnt removeObjectAtIndex:0]; 
    [self.recordUploadCnt addObject:[NSString stringWithFormat:@"%f",currentTime]]; 
} 
[[NSUserDefaults standardUserDefaults] setObject:self.recordUploadCnt forKey:KEY_SENSOR_UPLOAD]; 
[[NSUserDefaults standardUserDefaults] synchronize]; 

Exception Type: SIGSEGV 
Exception Codes: SEGV_MAPERR at 0xebfecbeb8 
Crashed Thread: 37 
Thread 37 Crashed: 
0 libobjc.A.dylib     0x0000000184980430 _objc_msgSend :16 (in libobjc.A.dylib) 
1 CoreFoundation     0x00000001856bf4c8 __CFPropertyListIsValidAux :52 (in CoreFoundation) 
2 CoreFoundation     0x00000001856c02a4 __CFPropertyListIsArrayPlistAux :40 (in CoreFoundation) 
3 CoreFoundation     0x00000001855e3900 _CFArrayApplyFunction :80 (in CoreFoundation) 
4 CoreFoundation     0x00000001856bf5fc __CFPropertyListIsValidAux :360 (in CoreFoundation) 
5 CoreFoundation     0x00000001855fc414 _CFPropertyListWrite :96 (in CoreFoundation) 
6 CoreFoundation     0x00000001855fbc14 _CFPropertyListCreateData :316 (in CoreFoundation) 
7 CoreFoundation     0x0000000185778f28 _CFPrefsEncodeKeyValuePairIntoMessage :504 (in CoreFoundation) 
8 CoreFoundation     0x0000000185689f94 -[CFPrefsPlistSource sendMessageSettingValue:forKey:] :136 (in CoreFoundation) 
9 CoreFoundation     0x00000001856886ec -[CFPrefsPlistSource alreadylocked_setValues:forKeys:count:from:] :440 (in CoreFoundation) 
10 CoreFoundation     0x0000000185756034 -[CFPrefsSource setValues:forKeys:count:removeValuesForKeys:count:from:] :220 (in CoreFoundation) 
11 CoreFoundation     0x00000001856b9150 -[CFPrefsSearchListSource alreadylocked_setValues:forKeys:count:from:] :584 (in CoreFoundation) 
12 CoreFoundation     0x0000000185756034 -[CFPrefsSource setValues:forKeys:count:removeValuesForKeys:count:from:] :220 (in CoreFoundation) 
13 CoreFoundation     0x00000001857563f4 -[CFPrefsSource setValue:forKey:from:] :64 (in CoreFoundation) 
14 CoreFoundation     0x00000001856bbfa4 __108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke :260 (in CoreFoundation) 
15 CoreFoundation     0x00000001856bb7c8 _normalizeQuintuplet :356 (in CoreFoundation) 
16 CoreFoundation     0x00000001856bbe94 -[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:] :108 (in CoreFoundation) 
17 CoreFoundation     0x000000018576008c -[_CFXPreferences setValue:forKey:appIdentifier:container:configurationURL:] :92 (in CoreFoundation) 
18 CoreFoundation     0x000000018576370c _CFPreferencesSetAppValueWithContainer :128 (in CoreFoundation) 
19 Foundation      0x000000018601bf80 -[NSUserDefaults(NSUserDefaults) setObject:forKey:] :68 (in Foundation) 
+0

동시성에 문제가있는 것처럼 보입니다. '@sync' 또는 직렬 디스패치 큐를 사용하여 배열이나 사용자 기본 키에 대한 동시 업데이트가 없도록해야합니다. 또한, 이것은 적절한 싱글 톤 패턴이 아닙니다. 'init'에서'dispatch_once'를 사용해야합니다. – Paulw11

+0

@ Paulw11, 그건 의미가있어, 나는'dispatch_once'를 사용하여 게시물의'init' 메소드를 호출하는'sharedInstance' 메소드를 사용하고 있습니다. 이 충돌을 재현 할 수 있습니까? 나는 그것을 시도하지 않았다. – gabbler

+0

@ gabbber, 기본 객체는 NSData, NSString, NSNumber, NSDate, NSArray 또는 NSDictionary의 인스턴스 (또는 컬렉션의 인스턴스 조합) 인 속성 목록이어야합니다. 다른 유형의 객체를 저장하려면 일반적으로 객체 유형을 저장하여 NSData의 인스턴스를 만들어야합니다. StackOverflow 링크를 시도해보십시오. https://stackoverflow.com/questions/6696558/storing-data-to-nsuserdefaults – Ashish

답변

0

당신은 당신은 애플의 문서를 참조하여 직접 NSUserDefaults

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.recordUploadCnt]; 

[[NSUserDefaults standardUserDefaults] setObject:data forKey: KEY_SENSOR_UPLOAD]; 

[[NSUserDefaults standardUserDefaults] synchronize]; 
0

로 변경 가능한 개체를 저장하지 못할, 데이터 개체를 저장하려고 & 변환 : UserDefaults - Storing Default Objects

기본 객체는해야 NSData, NSString, NSNumber, NSDate, NSArray 또는 NSDictionary의 인스턴스 (또는 컬렉션, 인스턴스의 조합) 인 속성 목록이 될 수 있습니다. 다른 유형의 객체를 저장하려면 일반적으로 객체 유형을 저장하여 NSData의 인스턴스를 만들어야합니다.

당신은
NSData *arrayData = [NSKeyedArchiver archivedDataWithRootObject: self.recordUploadCnt]; 
[[NSUserDefaults standardUserDefaults] setObject:arrayData forKey: KEY_SENSOR_UPLOAD]; 

정확한 NSUserDefaults에 귀하의 추가 그것을하기 전에, 당신이 배열 값을 확인을 NSData로 변환 (이 시도하고 참조) mayneed.

나는 다음과 같은 시도하고 나를 위해 작동합니다

#import "ViewController.h" 

@interface ViewController() { 

} 

@property(nonatomic, strong) NSMutableArray* recordUploadCnt; 
@end 

NSString* const KEY_SENSOR_UPLOAD = @"recordUploadCnt"; 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self testArrayWithUserDefaults]; 
} 

-(void)testArrayWithUserDefaults { 

    double currentTime = [[NSDate date] timeIntervalSince1970]; 
    [self.recordUploadCnt addObject:[NSString stringWithFormat:@"%f",currentTime]]; 
    [[NSUserDefaults standardUserDefaults] setObject:self.recordUploadCnt forKey:KEY_SENSOR_UPLOAD]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 

    NSMutableArray* userDefaultsArray = (NSMutableArray *)[[NSUserDefaults standardUserDefaults] objectForKey:KEY_SENSOR_UPLOAD]; 
    NSLog(@"Array = %@", [NSString stringWithFormat:@"%f",currentTime]); 
} 

결과 : 배열 = 1512136898.293169 여기

작업 복사본의 스냅 샷입니다 :

enter image description here

+0

'self.recordUploadCnt'에는'NSString' 객체가 포함되어 있으므로 문제가되지 않습니다. 게시물에 대한 내 의견을 참조하십시오. – gabbler