1

UIImages の束を JPG として保存するメソッドがあり、アプリがクラッシュしています。メモリが解放されていないことが原因だと思います。画像を保存するために UIImageJPEGRepresentation を使用しています。自動解放プールにラップしていますが、機能していないようです。

       for (Images *anImage in images) {

            NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];

            NSString *fileName = [NSString stringWithFormat:@"%@-%i-%i-%i.jpg", appDelegate.currentUserName, appDelegate.reportId, aDefect.defectId, i];

            [UIImageJPEGRepresentation(anImage.image, 1) writeToFile:localImagePath atomically:NO];

            [p drain];

            i++;

        }

上記のコードを実行すると、アナライザーはますます多くのメモリが使用されていることを示し、最終的にはクラッシュします。行を削除すると - [UIImageJPEGRepresentation(anImage.image, 1) writeToFile:localImagePath atomically:NO]; それは正常に動作します。

参考までに、ループは NSManagedObjects の配列を反復処理します。

どんな助けでも大歓迎です!ありがとう

提案による新しいコードは次のとおりです-

- (void) convertImages {

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Report" inManagedObjectContext:context];
NSPredicate *predicate = [NSPredicate
                          predicateWithFormat:@"status != %@", @"Leads"];

[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
[fetchRequest setIncludesPropertyValues:NO];

NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

for (Report *aReport in fetchedObjects) {

    appDelegate.reportId = [aReport.reportId intValue];

    NSArray *defects = [self getAllItemDefects];

    for (ItemDefect *anItemDefect in defects) {

        NSArray *defectImages = [self getImages:[anItemDefect.itemDefectId intValue] isMainImage:NO];

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
        dispatch_async(queue, ^(void) {

            int i = 0;

            for (Images *anImage in defectImages) {

                NSString *fileName = [NSString stringWithFormat:@"%@-%i-%i-%i.jpg", appDelegate.currentUserName, [aReport.reportId intValue], [anItemDefect.itemDefectId intValue], i];

                NSString *localImagePath = [documentsDirectory stringByAppendingPathComponent:fileName];

                [UIImageJPEGRepresentation(anImage.image, 1) writeToFile:localImagePath atomically:NO];

                i++;

            }

            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"FINISH: do eventual operations");
            });

        });

    }

}

}

それは私にこのエラーを与えます-

ここに画像の説明を入力

ディスパッチ ブロック内にdefectImages配列をロードしても、何もしません。ご協力いただきありがとうございます。

編集 - CoreData はスレッド セーフではないため、この問題を解決するために新しい FetchRequests と ObjectContexts を宣言しました。不正なアクセス エラーは発生しなくなりましたが、メモリ不足に戻りました。コードを簡略化しましたが、この状態ではメモリ リークが発生します -

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
        dispatch_async(queue, ^(void) {

            NSFetchRequest *backgroundFetchRequest = [[NSFetchRequest alloc] init];

            NSManagedObjectContext *backgroundContext = [[[NSManagedObjectContext alloc] init] autorelease];
            [backgroundContext setPersistentStoreCoordinator:persistentStoreCoordinator];
            NSEntityDescription *entity = [NSEntityDescription entityForName:@"Images" inManagedObjectContext:backgroundContext];
            NSPredicate *predicate = [NSPredicate
                                      predicateWithFormat:@"itemDefectId=%i AND reportId=%i AND isMainImage=%i", itemDefectId, appDelegate.reportId, NO];

            [backgroundFetchRequest setEntity:entity];
            [backgroundFetchRequest setIncludesPropertyValues:NO];
            [backgroundFetchRequest setPredicate:predicate];

            NSArray *defectImages = [backgroundContext executeFetchRequest:backgroundFetchRequest error:&error];

            NSMutableArray *images = [[NSMutableArray alloc] init];

            for (Images *anImage in defectImages) {
                [images addObject:anImage.image];
            }

            [images release];

            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"FINISH: do eventual operations");
            });
        });
4

1 に答える 1

0

これは良い解決策ではありません。GCD を使用してください。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

for (int i=0; i<[images count]; i++) {

    dispatch_async(queue, ^(void) {

        Images *anImage = (Images *)[images objectAtIndex:i];
        NSString *fileName = [NSString stringWithFormat:@"%@-%i-%i-%i.jpg", appDelegate.currentUserName, appDelegate.reportId, aDefect.defectId, i];

        [UIImageJPEGRepresentation(anImage.image, 1) writeToFile:localImagePath atomically:NO];

        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"FINISH to write image %d", i);
        });

    });
}

さらに、コードでは、ファイル名は常に同じであり、変更されず、使用されません。あなたのコードは部分的ですか?

ただし、非同期処理にはディスパッチャを使用してください。

于 2013-11-15T01:07:49.437 に答える