2011-05-09 8 views
2

NSStringのタイトル、NSStringのテキスト、NSDateのcreationDateを保持するカスタム 'Entry'オブジェクトを使用する最初のiphone 'Diary'アプリを開発しています。 EntryオブジェクトのNSMutableArrayをアーカイブして、次にビューがロードされたときにそれらを取得しようとすると、アプリケーションがクラッシュします。私は、NSKeyedArchiversを使用するサンプルコードとサンプルの束を見てきましたが、なぜそれが起こるのかまだ分かりませんでした。私はエントリを保持する配列の初期化に問題がある推測していますが、ここではわからない...NSKeyedArchivers/NSKeyedUnarchiversを使用すると、アプリがクラッシュする理由を特定できません。

は多分あなたは私が永続的に監督しているものを見つけることができ、コードが...」

//--------- Entry.m--------------- 

- (id) initWithCoder:(NSCoder *)aDecoder{ 

if ((self = [super init])) { 
    self.title = [[aDecoder decodeObjectForKey:@"title"] retain]; 
    self.text = [[aDecoder decodeObjectForKey:@"text"] retain]; 
    self.created = [[aDecoder decodeObjectForKey:@"created"] retain]; 
} 
return self; 

} 

- (void) encodeWithCoder:(NSCoder *)aCoder{ 

[aCoder encodeObject:self.title forKey:@"title"]; 
[aCoder encodeObject:self.text forKey:@"text"]; 
[aCoder encodeObject:self.created forKey:@"created"]; 

} 

//-------------- Diary View Controller.m 

- (NSString *)dataFilePath { 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
    NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
return [documentsDirectory stringByAppendingPathComponent:kFilename]; 
} 

- (void) writeDataToArchive { 
NSMutableData *data = [[NSMutableData alloc] init]; 
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] 
          initForWritingWithMutableData:data]; 

[archiver encodeObject:self.entriesArray forKey:@"entriesArray"]; 
[archiver finishEncoding]; 
BOOL result = [data writeToFile:[self dataFilePath] atomically:YES]; 
[archiver release]; 
[data release];  
} 

- (void)addItem:sender { 
int count = [entriesArray count] +1;  
NSString *newEntryTitle = [NSString stringWithFormat:@"Entry %d", count];  
Entry *anEntry = [[Entry alloc] initWithTitle:newEntryTitle text:@"-" 
     created:[NSDate date]]; 
[entriesArray addObject:anEntry]; 
[self.tableView reloadData]; 

[anEntry release]; 
[self writeDataToArchive]; 
} 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 
NSString *filePath = [self dataFilePath]; 
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {  
    NSData *data = [[NSMutableData alloc] 
        initWithContentsOfFile:[self dataFilePath]]; 

    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] 
      initForReadingWithData:data]; 
    NSMutableArray *array = [unarchiver decodeObjectForKey:@"entriesArray"];  
    entriesArray = [array mutableCopy]; 
    [array release]; 
    [unarchiver finishDecoding]; 
    [unarchiver release]; 
    [data release]; 
} 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: 
    (NSIndexPath *)indexPath 
{ 
    // ... some other stuff 
    NSUInteger row = indexPath.row; 
    Entry *entry = [entriesArray objectAtIndex:row]; 

    cell.textLabel.text = entry.title; 
    return cell; 
} 

どうもありがとうございました。

+0

どこがクラッシュしますか? – JeremyP

答えて

2

あなたはそれを所有していないので、あなたはviewDidLoadarrayを解放するべきではありません。

他のメモリ管理ISSのカップルがあるのでCocoa memory management Rulesを確認してくださいあなたのコードのues。具体的には、あなたのinitWithCoder:方法で

self.title = [[aDecoder decodeObjectForKey:@"title"] retain]; 
self.text = [[aDecoder decodeObjectForKey:@"text"] retain]; 
self.created = [[aDecoder decodeObjectForKey:@"created"] retain]; 

すべてのプロパティを保持またはコピーしているという仮定に漏れます。

+0

ありがとう、私はそれを調べます。 具体的には、アプリケーションが読み込まれたときにクラッシュしました。私はそこまでブレークポイントを使って追跡することができましたが、どのラインがそれを引き起こしているのかは具体的に分かりませんでした。 – dg024

+0

私は最初にタイトルとテキストをNSStringsとして持っていて、それらにプロパティ 'copy'を持っていたので、 'retain's to'のコピーを変更しました。ありがとう。 – dg024

3

NSKeyedUnarchiversを使用して配列を読み込むと、常に変更できないコピーが戻されます。 * arrayをNSArrayとして宣言するか、配列全体をまとめて削除する必要があります。

entriesArray = [[unarchiver decodeObjectForKey:@"entriesArray"] mutableCopy]; 

@JeremyPは別の問題を指摘しています。 *配列を確保したり保持したりしていないので解放しないでください。

関連する問題