0

NSCoding 프로토콜을 구현하는 클래스 알림이 있습니다.NSUserDefaults가 내 사용자 지정 개체를 저장하고 읽을 수 없습니다.

+ (void) initialize 
{ 
    NSUserDefaults* defaults=[NSUserDefaults standardUserDefaults]; 
    [defaults registerDefaults: [NSDictionary dictionaryWithObject: [NSKeyedArchiver archivedDataWithRootObject: [NSArray array]] forKey: @"notificationsData"]]; 
} 


- (id) init 
{ 
    self=[super init]; 
    if(self) 
    { 
     NSUserDefaults* defaults=[NSUserDefaults standardUserDefaults]; 
     NSData* notificationsData=[defaults objectForKey: @"notificationsData"]; 
     notifications= [[NSKeyedUnarchiver unarchiveObjectWithData: notificationsData]mutableCopy]; 
    } 
    return self; 
} 

- (void) applicationWillTerminate:(NSNotification *)notification 
{ 
    NSUserDefaults* defaults=[NSUserDefaults standardUserDefaults]; 
    NSData* notificationsData=[NSKeyedArchiver archivedDataWithRootObject: notifications]; 
    [defaults setObject: notificationsData forKey: @"notificationsData"]; 
} 

알림 클래스 텍스트 :
내가 notifications.I의 배열 NSUserDefaults.In 내 응용 프로그램 위임 알림과 알림을 저장하기 위해 노력하고 있습니다 내 응용 프로그램 대리인의 objects.That 알림을 포함하는있는 NSMutableArray이다 제목 유형있는 NSString (모두 READWRITE)의, 그리고 날짜는 유형있는 NSDate (또한이 READWRITE 속성이) .This 내가 NSCoding 프로토콜을 구현하는 방법입니다 :

:

- (void) encodeWithCoder:(NSCoder *)aCoder 
{ 
    [aCoder encodeObject: date forKey: @"date"]; 
    [aCoder encodeObject: title forKey: @"title"]; 
    [aCoder encodeObject: text forKey: @"text"]; 
} 

- (id) initWithCoder:(NSCoder *)aDecoder 
{ 
    self=[super init]; 
    if(self) 
    { 
     date=[aDecoder decodeObjectForKey: @"data"]; 
     title=[aDecoder decodeObjectForKey: @"title"]; 
     text=[aDecoder decodeObjectForKey: @"text"]; 
    } 
    return self; 
} 

그래서 나는이 문제가를

  1. NSKeyedArchiver를 사용하여 텍스트를 인코딩하려고하면 응용 프로그램이 종료 될 때 알림 클래스에서 EXC_BAD_ACCESS가 발생합니다.
  2. 응용 프로그램이 시작될 때 알림은 저장되지 않고 배열의 길이는 항상 0입니다.

    - (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView 
    { 
        return [notifications count]; 
    } 
    
    - (id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 
    { 
        // Debug 
        id obj=[[notifications objectAtIndex: row] valueForKey: [tableColumn identifier]]; 
        Class class=[obj class]; 
        // What you see above is just for debug purposes 
        return [[notifications objectAtIndex: row] valueForKey: [tableColumn identifier]]; 
    } 
    
    - (void) tableViewSelectionDidChange:(NSNotification *)notification 
    { 
        NSInteger row=[tableView selectedRow]; 
        if(row >= 0 && row< [notifications count]) 
         [removeButton setEnabled: YES]; 
        else 
         [removeButton setEnabled: NO]; 
    } 
    

    라는 마지막 방법은 다음과 같습니다

업데이트 : 응용 프로그램이 crashes.There (나는 데이터를 표시하기 위해 테이블 ​​뷰를 사용하고 있습니다) 볼 수있는 더 많은 코드가 어디에 더 디버그으로 내가 발견 이 :

- (id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row; 

아마 문제는 데이터가 어떻게 든 손상 및이 방법에 충돌하지 않는 응용 프로그램을 valid.Anyway되지 않은이 메소드에 의해 반환 된 값,하지만이 방법 후된다는 점이다.
사용자 기본값에서 두 개의 개체를로드하는 경우 충돌이 발생하기 전에 하나의 개체 만로드됩니다. 따라서 메서드가 한 번 호출됩니다.
그러나 나는 아직도 충돌의 진짜 이유를 얻을 수 없습니다.

더 코드 :

- (IBAction) addNotification :(id)sender 
{ 
    Notification* notification=[[Notification alloc]init]; 
    [notification setDate: [datePicker dateValue]]; 
    [notification setText: [textView string]]; 
    [notifications addObject: notification]; 
    [tableView reloadData]; 
} 

- (IBAction)removeNotification:(id)sender 
{ 
    [notifications removeObjectAtIndex: [tableView selectedRow]]; 
    [tableView reloadData]; 
} 

에 addNotification 및 removeNotification이 두 버튼에 의해 트리거됩니다.

편집 : 내가 ARC를 사용하지 않고있는 것을 발견했지만, 앱을 켜더라도이를 해제합니다.

답변

1

응용 프로그램이 갑자기 종료 할 때 자동으로 일어나지 않을 것입니다 때문에 당신은 [NSUserDefaults 동기화] 호출 할 필요가 있습니다

date=[aDecoder decodeObjectForKey: @"data"]; 

@"data" 인코더 일치하지 않습니다 라인에서

- (void) applicationWillTerminate:(NSNotification *)notification 
{ 
    NSUserDefaults* defaults=[NSUserDefaults standardUserDefaults]; 
    NSData* notificationsData=[NSKeyedArchiver archivedDataWithRootObject: notifications]; 
    [defaults setObject: notificationsData forKey: @"notificationsData"]; 
    [defaults synchronize]; 
} 
+0

그래, 어쨌든 충돌이 발생해도 여전히 문제가 있습니다. –

+1

'NSData * notificationsData = [NSKeyedArchiver archivedDataWithRootObject : notifications];를 NSData * notificationsData = [NSKeyedArchiver archivedDataWithRootObject : @ []];로 대체하면 어떻게됩니까? –

+0

이 경우 예외가 발생하지 않고 애플리케이션이 원활하게 실행됩니다. 물론 배열이 비어 있기 때문에 이전 실행에서 알림을 복구 할 수 없습니다. 프로토콜 구현 방법에 문제가 있음을 알 수 있습니다. –

2

을 키. 당신이 정말로 원하는 :

date=[aDecoder decodeObjectForKey: @"date"]; 
+0

고마워, 지금은 그것을 대체했습니다. 그러나 프로그램은 여전히 ​​충돌합니다. –

+0

앱을 완전히 삭제 했습니까? 이전 사용자 기본값이 여전히있을 수 있습니다. – thelaws

+0

NSUserDefault의 resetStandardUserDefaults 메서드를 사용했지만 응용 프로그램이 계속 충돌합니다. –

0

당신은 무엇이 잘못된 것인지 추측 할 수있다 : 내 나쁜, 나는 ARC 수 있도록 잊고 일부 개체는 때이 안 발표했다.

관련 문제