1

次の問題で私を助けてください:

- (NSDictionary *)getGamesList
{
    NSMutableDictionary *gamesDictionary = [[NSMutableDictionary dictionary] retain];
// I was trying to change this on the commented code below, but did have no effect
//    NSMutableDictionary *gamesDictionary = [[NSMutableDictionary alloc] init];
//    [gamesDictionary retain];
    while (sqlite3_step(statement) == SQLITE_ROW)
    {
        NSString *key = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
        NSArray *gameDate = [key componentsSeparatedByString:@" "];
        NSNumber *_id = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, 0)];
        NSString *date_time = [NSString stringWithFormat:@"%@, %@",[gameDate objectAtIndex:0],[gameDate objectAtIndex:2]];
        if (![gamesDictionary valueForKey:date_time]) [gamesDictionary setValue:[NSMutableArray array] forKey:date_time];
        [[gamesDictionary valueForKey:date_time] addObject:[[_id copy] autorelease]];
        [_id release];
    }
    sqlite3_reset(statement);
    return gamesDictionary;
}

リークは別のクラスの別のメソッドで始まり、getGamesListメソッドが次のように呼び出されます。

NSMutableDictionary *gamesDictionary;
gamesDictionary = [[NSMutableDictionary dictionaryWithDictionary:[appDelegate getGamesList]] retain];

その後、文字列内のNSCFArrayを指す多くのリークがあります。

NSArray *keys = [[NSArray arrayWithArray:[gamesDictionary allKeys]] retain]; 

この方法では:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    NSArray *keys = [[NSArray arrayWithArray:[gamesDictionary allKeys]] retain];
    if ([keys count] != 0)    return [[keys objectAtIndex:section] uppercaseString];
    return @"";
}

これらは相互に関連していると思いますが、それでもすべてのメモリ管理のヒントを理解することはできません。どうもありがとう!

4

2 に答える 2

2

何年も Cocoa を使用していませんでした (そのため、正確な答えは言えません :/)。しかし、あなたの問題はretain、オブジェクトに対して体系的に使用していることだと思います。

オブジェクト参照カウントが 0 になることはないため、すべての辞書はメモリに保持され、解放されません。

retainon[NSArray arrayWithArray]とを削除してみてください[NSMutableDictionary dictionaryWithDictionary

http://en.wikibooks.org/wiki/Programming_Mac_OS_X_with_Cocoa_for_beginners/Some_Cocoa_essential_principles#Retain_and_Release

于 2010-03-06T09:26:02.700 に答える
1

配列を過剰に保持しているようです。

を作成するgamesDictionaryと、保持カウント +1 で作成されます。その後、保持します(カウントは+2になります)。この関数の外で値を取得すると、再び保持されます (count は +3 になります)。

オブジェクトを作成する場合、そのメモリ管理を担当するのは正しいです。また、メソッドからオブジェクトを取得する場合、関数のスパンよりも長く保持したい場合は、それを保持する必要があります。あなたの場合、オブジェクトのいくつかのプロパティを取得したいだけなので、それを保持する必要はありません。

ここに提案があります:

- (NSDictionary *)getGamesList
{
    NSMutableDictionary *gamesDictionary = [NSMutableDictionary dictionary]; // Remove the retain.
    while (sqlite3_step(statement) == SQLITE_ROW)
    {
        NSString *key = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
        NSArray *gameDate = [key componentsSeparatedByString:@" "];
        NSNumber *_id = [[NSNumber alloc] initWithInt:sqlite3_column_int(statement, 0)];
        NSString *date_time = [NSString stringWithFormat:@"%@, %@",[gameDate objectAtIndex:0],[gameDate objectAtIndex:2]];
        if (![gamesDictionary valueForKey:date_time]) [gamesDictionary setValue:[NSMutableArray array] forKey:date_time];
        [[gamesDictionary valueForKey:date_time] addObject:[[_id copy] autorelease]];
        [_id release];
    }
    sqlite3_reset(statement);
    return gamesDictionary; 
}

この次のビットは厄介です。新しい辞書を作成して保持します。元の辞書は自動解放されないため、カウントは減少せず、常にハングアップします。新しい辞書を作成するのではなく、辞書を割り当てるだけです。

NSMutableDictionary *gamesDictionary = [[appDelegate getGamesList] retain];
// Retaining it, becuase it looks like it's used elsewhere.

さて、この方法では:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    NSString *returnString;
    // Don't need to retain the keys because you are only using it within the function
    // and since you didn't alloc, copy or retain the array it contains, you aren't responsible for it's memory management.
    NSArray *keys = [NSArray arrayWithArray:[gamesDictionary allKeys]];
    if ([keys count] != 0) {
        returnString = [[NSString alloc] initWithString:[[keys objectAtIndex:section] uppercaseString]];
        return [returnString autorelease];
    }
    return @"";
}
于 2010-03-06T11:02:27.317 に答える