0

ListControllerファイルにショップのリストがあります。私はsqliteデータベースをセットアップしました。そこには60のショップが保存されています。リストの一番上に検索バーがあります。

dbデータのロードと保存を担当するDataControllerというクラスを作成しました。

@interface DataController : NSObject {
 sqlite3 *database;
 NSArray *shops;    
 NSDictionary* dictionaryOfShops;
}

@property (nonatomic, retain) NSDictionary *dictionaryOfShops;
@property (nonatomic, retain) NSArray* shops;
-(void)initializeShops;

initializeShopsメソッドは、データベースからデータをロードし、次のように結果を2つの小道具に保存します。

-(void)initializeShops{
    [dictionaryOfShops release];
    [shops release];

    NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease];

    if (sqlite3_open(....))
    NSString *query = ....
    if (sqlite3_prepare_v2(database, [query UTF8String],-1, &statement, nil) ==   SQLITE_OK) 
    {
        while (sqlite3_step(statement) == SQLITE_ROW) {

           int rId = sqlite3_column_int(statement, 0);
           char *rName = (char *)sqlite3_column_text(statement, 1);

           Shop* s  = [[Shop alloc] init];
           s.ID = rId;
           if(sName != nil) s.Name = [NSString stringWithUTF8String:rName];

               NSString *shopID = [[NSString alloc] initWithFormat:@"%d",s.ID];
           [dictionary setObject:s forKey:shopID];
           [shopID release];
           [s release];         
        }
        sqlite3_finalize(statement);
    }
    [query release];

    dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
    shops =    [[NSArray alloc] initWithArray:[dictionary allValues]];

    dictionary = nil;
    [dictionary release];

       //Sorting
       NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES];
    NSArray *sortedList =[self.shops sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
    self.shops = sortedList; 
    [sort release];
}

問題は、ユーザーが検索バーにテキストを入力すると、クエリの値を変更して(LIKE ....を追加)、initializeShopsメソッドを再度呼び出すことです。この2回目は、(Shopクラスのプロパティに関連して)非常に多くのリークが発生し、NSDictionaryとNSArrayもリークします。

これを投稿する前に、さまざまな解決策を試しましたが、少なくともinitilizeShopsを初めて呼び出したときに何もリークしません。

私は本当にそれに固執しているので、私はどんな提案も受け入れます。

もっと:

本当に奇妙なことは、私のvar辞書と2つの小道具店とdictionaryOfShopsのメモリ管理です。このコードで

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
//add data to dictionary 
dictionaryOfShops = [[NSDictionary alloc] initWithDictionary:dictionary];
shops =    [[NSArray alloc] initWithArray:[dictionary allValues]];
[dictionary release]

dictionaryOfShopsとshopsが2つのプロパティ(非アトミック、保持)で合成されていることを考えると、リークなしで値を変更するにはどうすればよいですか?

このメソッドを最初に通過したときは何もリークされません。2回目からは非常に多くのオブジェクト(コレクションのコンテンツ)がリークし始めます。

4

3 に答える 3

2

最初の質問は、なぜCoreDataを使用しないのかということです。 より高速になり、必要なコードが少なくなり、長期にわたって保守が大幅に容易になる可能性が非常に高くなります。率直に言うと; SQLiteは一見難しいです。始めるのは簡単ですが、正しく理解するのは非常に困難です。

いずれにせよ、のメモリ管理dictionaryは間違っています。kennyTMが提案したように、nil割り当てとリリースの順序を入れ替えたため、クラッシュすることはありません。自動リリースされた辞書を作成しないことをお勧めします。

そうでなければ、書かれたコードは一見するとかなり漏れがないように見えます。それで:

  1. さらにコードを提供できますか?他の場所で起こっている興味深い記憶はありますか?

  2. スレッド(またはNSOperationQueue)を使用していますか?

  3. Leaks機器の下で実行し、リークされている特定のオブジェクトの割り当てのバックトレースを取得しましたか?

于 2010-01-09T20:52:46.600 に答える
1
dictionary = nil;
[dictionary release];

これらの2つのステートメントを交換してください。この形式では[nil release]、どちらがノーオペレーションであるかを意味します。

于 2010-01-09T20:46:46.940 に答える
0

わかりました、エラーが見つかりました。私のクラスのショップでは、メソッドを実装していなかったことに気づきました

 -(void)dealloc

そのため、(新しい割り当ての準備のために)古い辞書を解放しても、その中のすべてのフィールドが解放されませんでした。

于 2010-01-10T15:16:10.570 に答える