1

私のアプリでは、コアデータを使用して情報を保存しています。アプリが最初に起動されると、データを取得するために次のコード ブロックが呼び出されます。

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName: @"Customer" inManagedObjectContext: managedObjectContext];
request.entity = entity;

NSError *error = nil;

Array = [[managedObjectContext executeFetchRequest: request error: &error] mutableCopy];
NSArray * reversedArray = [[Array reverseObjectEnumerator] allObjects];
[Array release];
Array = nil;
[request release];
[error release];

したがって、すべてが正しく機能しますが、解放されていない非常に大量のメモリが割り当てられており、それを理解できないようです。以下のスクリーンショットで確認できます。どんな助けでも素晴らしいでしょう。

ここに画像の説明を入力

ここに画像の説明を入力

編集

私は当初、以下の回答を受け入れましたが、問題が 100% 解消されるわけではないようです。CFData (ストア) はまだ解放されていない大量のメモリを割り当てています。これは最終的に、iPad 4 でのみテストしていたため、以下の回答を受け入れたときに経験しなかった iPad 2 でクラッシュを引き起こしています。これですべてが解決することを願っています。

編集2

そのため、より多くのテストとデバッグを行ってきましたが、コア データに追加されるエントリが多いほど、CFData (ストア) が大きくなっているようです。現在、データベースには 10 個の個別のエントリしかなく、アプリを開いたときのそれらの取得による割り当ては 25 MB を超えています。主エンティティ「顧客」には、他のより大きなエンティティとの複数の関係があります。そのため、「顧客」のフェッチを実行すると、関係のあるすべてのエンティティがフェッチされ、大量のメモリ割り当てが発生します。この問題を回避する方法はありますか?

エントリの追加方法と取得方法を設定するには、もっと良い方法が必要だと思います。

エントリを作成するコードは次のとおりです。

- (void) addItem
{
// Insert a new record in the database
Customer * customerItem = [NSEntityDescription insertNewObjectForEntityForName: @"Customer" inManagedObjectContext: managedObjectContext];

System * system = [NSEntityDescription insertNewObjectForEntityForName: @"System" inManagedObjectContext: managedObjectContext];

Form1 * form1 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form1" inManagedObjectContext: managedObjectContext];

Form2 * form2 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form2" inManagedObjectContext: managedObjectContext];

Form3 * form3 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form3" inManagedObjectContext: managedObjectContext];

Form4 * form4 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form4" inManagedObjectContext: managedObjectContext];

Form6 * form6 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form6" inManagedObjectContext: managedObjectContext];

Form7 * form7 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form7" inManagedObjectContext: managedObjectContext];

Form8 * form8 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form8" inManagedObjectContext: managedObjectContext];

Form9 * form9 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form9" inManagedObjectContext: managedObjectContext];

Form10 * form10 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form10" inManagedObjectContext: managedObjectContext];

Form11 * form11 =  [NSEntityDescription insertNewObjectForEntityForName: @"Form11" inManagedObjectContext: managedObjectContext];

customerItem.system = system;
customerItem.form1 = form1;
customerItem.form2 = form2;
customerItem.form3 = form3;
customerItem.form4 = form4;
customerItem.form6 = form6;
customerItem.form7 = form7;
customerItem.form8 = form8;
customerItem.form9 = form9;
customerItem.form10 = form10;
customerItem.form11 = form11;

// Insert a new item in the table's data source
[customerArray insertObject: customerItem atIndex: 0];

[managedObjectContext save: &error];

// Insert a new row in the table
NSIndexPath *indexPath = [NSIndexPath indexPathForRow: 0 inSection: 0];
[table insertRowsAtIndexPaths: [NSArray arrayWithObject: indexPath] withRowAnimation: UITableViewRowAnimationFade];
}
4

1 に答える 1

1

コア データには、その機能を実行するために必要な長寿命のメモリがある程度あります。@autoreleaseとはいえ、次のように、このコードをプールにラップすることで、ここでメモリの使用を最小限に抑えることができます。

@autoreleasepool {
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName: @"Customer" inManagedObjectContext: managedObjectContext];
    request.entity = entity;

    NSError *error = nil;

    Array = [[managedObjectContext executeFetchRequest: request error: &error] mutableCopy];
    NSArray * reversedArray = [[[Array reverseObjectEnumerator] allObjects] retain];
    [Array release];
    Array = nil;
    [request release];
    [error release];
}
[reversedArray autorelease];

作成したすべてのオブジェクトを慎重に解放したとしても、自動解放パターンはシステム フレームワーク全体で広く使用されています。

this を追加すると、プールのスコープの終了後も存続させるため@autoreleasepoolに保持する必要があることに注意してください。reversedArray後で追加[reversedArray autorelease]したので、コードは投稿したコードと意味的に同じです(フェッチリクエストの実行によって作成された自動解放されたオブジェクトの解放を除く)。

于 2013-01-19T19:59:19.430 に答える