0

NSCodingプロトコルを実装するクラスNotificationがあります。
通知の配列があります。NSUserDefaultsを使用して通知を保存しようとしています。アプリのデリゲート通知には、通知オブジェクトを含むNSMutableArrayがあります。これがアプリのデリゲートです。

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

Notificationクラスでは、テキストとタイトルはタイプNSString(両方とも読み取り/書き込み)であり、日付はタイプNSDateです(これにも読み取り/書き込みプロパティがあります)。これは、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を使用してテキストをエンコードしようとすると、NotificationクラスでEXC_BAD_ACCESSが取得されます。
  2. 通知は保存されず、アプリケーションの起動時に配列は常にロングゼロになります。

更新:より多くのデバッグで、アプリケーションがクラッシュする場所を発見しました。表示するコードがさらにあります(データを表示するためにテーブルビューを使用しています):

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

最後に呼び出されるメソッドは次のとおりです。

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

おそらく問題は、データが何らかの理由で破損していて、このメソッドによって返される値が無効であるということです。とにかく、アプリはこのメソッドではクラッシュしませんが、このメソッドの後でクラッシュします。
ユーザーのデフォルトから2つのオブジェクトをロードすると、クラッシュする前に1つのオブジェクトのみがロードされます(したがって、メソッドは1回呼び出されます)。
しかし、私はまだクラッシュの本当の理由を知ることができません。

その他のコード:

- (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を使用していないことを発見しましたが、それをオンにしてもアプリがクラッシュします。

4

3 に答える 3

2

行で:

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

@"data"エンコーダキーと一致しません。あなたは本当に欲しい:

date=[aDecoder decodeObjectForKey: @"date"];
于 2012-10-29T18:32:08.407 に答える
1

アプリケーションが突然終了したときに自動的に発生しないため、[NSUserDefaultssynchronize]を呼び出す必要がある場合があります。

- (void) applicationWillTerminate:(NSNotification *)notification
{
    NSUserDefaults* defaults=[NSUserDefaults standardUserDefaults];
    NSData* notificationsData=[NSKeyedArchiver archivedDataWithRootObject: notifications];
    [defaults setObject: notificationsData forKey: @"notificationsData"];
    [defaults synchronize];
}
于 2012-10-29T17:54:59.793 に答える
0

何が悪かったのか推測できませんでした。残念ながら、ARCを有効にするのを忘れてしまい、一部のオブジェクトがリリースされるべきではないときにリリースされました。

于 2012-10-30T15:27:20.930 に答える