1

約 200 個の NSManagedObject を取得したいのですが、それぞれのサイズは約 5Mb です。executeFetchRequest を使用すると、メモリ警告が表示され、アプリがクラッシュします (フェッチされた NSManagedObjects が iPhone の RAM に表示されるため)。executeFetchRequest を使用できる場合は、sortdescriptor を使用して ID でデータを並べ替えることができます。しかし、できません (または、適切なプロパティを NSFetchRequest に設定する必要があるかもしれませんが、どのプロパティかわかりません)。そのため、大量のデータをロードするために別のアプローチを使用しました。多くのエンティティ SpecificImage を持つエンティティ アルバムがあります。そして、このコードを使用して、現在のアルバムのすべての画像を取得します。

- (NSMutableSet *)getAllSpecificImages
{
        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.CurrentCategoryItemID];
        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");
            return nil;
        }
        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];
            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.CurrentCategoryItemID = newID;
        }

    NSMutableSet *set = [object mutableSetValueForKey:@"specificImages"];
    return set;
}

次に、NSManagedObjects の配列を取得します

NSMutableArray *array = [NSMutableArray arrayWithArray:[setOfManagedObjectsSpecificImages allObjects]];

しかし、この NSManagedObjects の並べ替えられた配列を取得しようとすると、再びメモリ警告が表示され、アプリがクラッシュします。使ってみた

NSSortDescriptor *sortDiscriptor = [NSSortDescriptor sortDescriptorWithKey:@"id" ascending:YES];
[array sortUsingDescriptors:[NSArray arrayWithObject:sortDiscriptor]];

[self quickSort:array left:0 right:([array count] - 1)];

どこ

- (void)quickSort: (NSMutableArray *)arr left:(NSInteger)left right:(NSInteger) right
{
    @autoreleasepool {
        int i = left, j = right;

        int pivot = [((SpecificImage *)[arr objectAtIndex:(left + right) / 2]).id intValue];



        /* partition */

        while (i <= j) {
            while ([((SpecificImage *)[arr objectAtIndex:i]).id intValue] < pivot)
            {

                i++;
            }

            while ([((SpecificImage *)[arr objectAtIndex:j]).id intValue] > pivot)
            {

                j--;
            }

            if (i <= j) {

                [arr exchangeObjectAtIndex:i withObjectAtIndex:j];

                i++;

                j--;

            }

        };


        /* recursion */

        if (left < j)
        {
            [self quickSort:arr left:left right:j];
        }

        if (i < right)
        {
            [self quickSort:arr left:i right:right];
        }

    }

}

しかし、それは役に立ちませんでした。

私の見解では、一連の NSManagedObjects を取得すると、それらは RAM にありません。ただし、並べ替え中に RAM に表示されます。

ソートされた NSMutableSet を取得したかった (設定しようとした:

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"specificImages.id" ascending:YES];

しかし、私は得ました

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'to-many key not allowed here'

この問題はNSSortDescriptor対多関係のもう1つの質問であると説明しました

私の観点から、私は2つのアプローチを見ています:1)executeFetchRequest、しかし提供:オブジェクトはRAMに表示されません(方法はわかりませんが、それが可能であることはほとんど確信しています)2)クイックを変更します提供する並べ替え: オブジェクトは RAM に表示されません

更新 ここに私のコードがあります。ここでは、executeFetchRequest を使用してオブジェクトをフェッチしようとしています (オブジェクトは RAM にあり、(RAM ではなく) 障害オブジェクトにしたい):

+ (NSMutableSet *)GetImagesWithPredicate:(NSPredicate *)predicate
{
    NSString *entityName = kEntityName;
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];;
    NSManagedObjectContext *context = appDelegate.managedObjectContext;
    NSEntityDescription *entityDesctiption = [NSEntityDescription 
                                              entityForName: entityName
                                              inManagedObjectContext:context];

    // find object
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDesctiption];
    [request setPredicate:predicate];
    NSArray *objects = [context executeFetchRequest:request error:nil];
    [request release];
    if (objects == nil)
    {
        NSLog(@"there was an error");
        return nil;
    }
    NSMutableSet *set = [NSMutableSet setWithArray:objects];
    return set;
}

ここで述語:

NSMutableArray *allID = [NSMutableArray array];
for (int i = 1; i < 639; i++)
{
      [allID addObject:[NSNumber numberWithInt:i]];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id in %@", allID];
4

2 に答える 2

3

tl;コードを読んでください。

CoreData には事があります。それはフォルトと呼ばれます。障害オブジェクトとは、データがまだストアにあるオブジェクトへの参照があることを意味します (「RAM にない」のバージョン)。オブジェクトをデフォルトにするには、valueForKey:メソッドを呼び出して任意のプロパティを取得する必要があります (これにより、関係を除くオブジェクト全体が読み込まれます)。並べ替えを行うと、コア データが内部的に呼び出さvalueForKey:れ、画像データが読み込まれます。

ImageDescriptorあなたへの私の提案:並べ替えに必要なすべてのプロパティを保持する場所のようなものと呼ばれる別のエンティティを作成します。このエンティティは、実際のバイナリ イメージ データと 1 対 1 の関係を保持し、必要な場合にのみフェッチします (つまり、遅延フェッチを使用します)。

于 2012-06-06T11:27:46.960 に答える
0

私はEimantasアプローチを使用しましたが、RAMにオブジェクトを記録せずにオブジェクトをフェッチする方法を学びました。使用しましたincludesPropertyValues

于 2012-06-07T11:13:30.073 に答える