1

コアデータベースに200個の5Mbレコードを挿入したいと思います。しかし、NSManagedObjectを保存すると、メモリが解放されず(自動解放されたプールは役に立ちませんでした)、30レコードを挿入した後、メモリ警告が表示され、アプリケーションがクラッシュしました。これが私のコードです

- (void)SaveItem
    {
        NSString *entityName = kEntityName;
        AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
        NSManagedObjectContext *context = appDelegate.managedObjectContext;
        NSEntityDescription *entityDesctiption = [NSEntityDescription 
                                                  entityForName: entityName
                                                  inManagedObjectContext:context];
        // check if town exists
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id == %d", self.imageID];
        NSFetchRequest *requestToCheckExistense = [[NSFetchRequest alloc] init];
        [requestToCheckExistense setEntity:entityDesctiption];
        [requestToCheckExistense setPredicate:predicate];
        NSArray *objects = [context executeFetchRequest:requestToCheckExistense error:nil];
        [requestToCheckExistense release];
        if (objects == nil)
        {
            NSLog(@"there was an error");
        }
        NSManagedObject *object;
        if ([objects count] > 0)
        {
            // edit item
            object = [objects objectAtIndex:0];
        }
        else
        {
            // if object doesn't exist, find max id to imlement autoincrement
            NSFetchRequest *request = [[NSFetchRequest alloc] init];
            [request setEntity:entityDesctiption];
            request.propertiesToFetch = [NSArray arrayWithObjects: @"id", nil];
            NSArray *allobjects = [context executeFetchRequest:request error:nil];
            [request release];
            NSInteger newID = 1;
            if ([allobjects count] > 0)
            {
                NSNumber *maxID = [allobjects valueForKeyPath:@"@max.id"];
                newID = [maxID intValue] + 1;
            }

            // write item
            object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context]; 
            [object setValue:[NSNumber numberWithInt:newID] forKey:@"id"];
            self.imageID = newID;
        }
        // fill NSManagedObject
        // size of objNSData is about 5MB
        NSMutableData *objNSData = [[DatabaseManager sharedDatabaseManager] encryptedDataFromImage:bigImage];
        [object setValue:objNSData forKey:@"big"];

         [context save:nil];
     }

コメントしたとき

[object setValue:objNSData forKey:@"big"];

すべてが大丈夫だった。

@autoreleasepoolにコードを追加しようとしましたが、役に立ちませんでした。データをデータベースに保存しても、iPhoneのRAMに残っていることはわかっています。このメモリからそれを解放する方法は?データベースから管理対象オブジェクトのセットを取得するとき、それらはRAMにありません(100個のオブジェクトを簡単に取得でき、それぞれに5Mbフィールドがあります)

4

3 に答える 3

2

問題を解決しました。[selfSaveItem]の呼び出し後; 使用しました

[context save];
[context reset];
[context save];

コンテキストからのすべてのNSManagedObjectsが解放されます。その操作の後、必要な数の大きなオブジェクトを追加できます

于 2012-06-06T08:55:02.847 に答える
2
 object =(tblEntity *) [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];


オブジェクトを型キャストしてみてください。これで問題が解決する場合があります

于 2012-06-05T11:45:54.697 に答える
1

作成時に NSManagedObject を所有していないため、解放した後でもコア データ スタックによって保持される場合があります (ループ内に含まれる autoreleasepool を使用する場合)。

これは役立つかもしれません:

  • managedobjectContext の取り消しマネージャーを nil に設定します。

    [context setUndoManager:nil];

  • 管理対象オブジェクトがループ内で時間どおりに解放されないため、そのオブジェクトのプロパティがどこにも保持されないようにしてください。

  • 次のように、すべてのループ自体をラップするのではなく、すべてのループ実行内に自動解放プールを追加してください。

    for(i;i<n;i++) {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        [obj saveItem];
        [pool drain];
     }
    
  • そのオブジェクトが NSManagedObjects の階層に属している場合、このオブジェクトをメモリから解放するには、このオブジェクトの所有者も解放する必要があります。

CoreDataのメモリ管理に関する Apple のドキュメントを確認できます。

警告: 大きなオブジェクト (> 1MB) を CoreData 内に格納することは Apple によって推奨されていません (この他の質問/回答を確認してください。 )

于 2012-06-05T12:28:50.880 に答える