1

アプリでメモリ使用量が上昇している (ただし、Instruments に明らかなリークがない) という問題があります。

MainViewController と PhotoViewController の 2 つの viewController を含むテスト プロジェクトがあります。MainViewController には、uinavigationcontroller pushViewController メソッドを介して PhotoViewController を単純にプッシュする単一のボタンが含まれています。

PhotoViewController では、ALAssetsLibrary を使用して UITableView に画像を設定しています。私は基本的にこれを2つの部分で行います。まず、カメラ ロールとフォトライブラリから画像を表示する必要があるため、使用可能な assetGroup を確認します。それが完了したら、別のメソッドを呼び出して、実際のアセットを列挙します。

奇妙な動作は次のとおりです。PhotoViewController をプッシュして、列挙全体を終了させ、UITableView に入力し、MainViewController に戻すと、すべて問題ありません。

ただし、(UITableiew の列挙と入力がまだ完了していない間に) PhotoViewCOntroller を繰り返しすばやくプッシュしてポップアウトすると、アプリが最終的に終了するまで、メモリ使用量が徐々に増加します。Instruments に明らかなリークは見られません。

関連するコードはわかりませんが、列挙に使用する 2 つの方法を次に示します。もちろん、dealloc では、関連する ivar を解放しています。

ポップ時に列挙をキャンセルする方法はありますか?

注記として、大幅にカスタマイズされていますが、このプロジェクト (https://github.com/elc/ELCImagePickerController) に基づいてテスト コードを作成しています。ただし、そのコードでテストしたところ、同じ問題が発生します。列挙するのに十分な ALAssets がある場合にのみ、メモリ使用量が上昇することに注意してください。数が少なすぎると、ポップアウトする前に列挙が終了します。

ありがとうございました!

- (void)getAssetGroups
{

    // Load Albums into assetGroups
    dispatch_async(dispatch_get_main_queue(), ^
       {
           NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

           // Group enumerator Block
           void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) 
           {
               if (group == nil) 
               {
                   // check what data is available

                   if([savedPhotosGroup numberOfAssets] > 0 && [libraryGroup numberOfAssets] > 0)
                   {
                       // User has both Camera Roll and Photo Library albums
                       self.tableData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                         savedPhotoAssets, NSLocalizedString(@"PHOTOPICKER_CAMERAROLL", nil),
                                         libraryPhotosAssets, NSLocalizedString(@"PHOTOPICKER_PHOTOLIBRARY", nil),
                                         nil];

                       self.sectionKeys = [NSArray arrayWithObjects:NSLocalizedString(@"PHOTOPICKER_CAMERAROLL", nil), NSLocalizedString(@"PHOTOPICKER_PHOTOLIBRARY", nil), nil];
                   }
                   else if([libraryGroup numberOfAssets] == 0)
                   {
                       // User only has Camera Roll
                       self.tableData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                         savedPhotoAssets, NSLocalizedString(@"PHOTOPICKER_CAMERAROLL", nil),
                                         nil];

                       self.sectionKeys = [NSArray arrayWithObjects:NSLocalizedString(@"PHOTOPICKER_CAMERAROLL", nil), nil];
                   }
                   else 
                   { 
                       //User only has Photo Library
                       self.tableData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                         libraryPhotosAssets, NSLocalizedString(@"PHOTOPICKER_PHOTOLIBRARY", nil),
                                         nil];

                       self.sectionKeys = [NSArray arrayWithObjects:NSLocalizedString(@"PHOTOPICKER_PHOTOLIBRARY", nil), nil];
                   }

                   NSLog(@"Done enumerating groups");
                   [self performSelectorInBackground:@selector(enumeratePhotos) withObject:nil];
                   [self.tview performSelector:@selector(reloadData) withObject:nil afterDelay:1];
                   return;
               }

               ALAssetsGroupType groupType = [[group valueForProperty:ALAssetsGroupPropertyType] unsignedIntValue];
               if(groupType == ALAssetsGroupSavedPhotos)
               {
                   self.savedPhotosGroup = group;
               }
               else if(groupType == ALAssetsGroupLibrary)
               {
                   self.libraryGroup = group;
               }
           };

           // Group Enumerator Failure Block
           void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {

               NSLog(@"A problem occured %@", [error description]);                                  
           };   

           // Enumerate Albums

           [library enumerateGroupsWithTypes: ALAssetsGroupSavedPhotos | ALAssetsGroupLibrary
                                  usingBlock:assetGroupEnumerator 
                                failureBlock:assetGroupEnumberatorFailure];

           NSLog(@"Draining pool");
           [pool drain];
       }); 
}

-(void)enumeratePhotos { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSLog(@"enumerating photos");
[savedPhotosGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) 
 {         
     if(result == nil) 
     {
         return;
     }

     CustomAsset *customAsset = [[[CustomAsset alloc] initWithAsset:result] autorelease];
     [customAsset setParent:self];

     [savedPhotoAssets addObject:customAsset];
 }]; 

[libraryGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) 
 {         
     if(result == nil) 
     {
         return;
     }         
     CustomAsset *customAsset = [[[CustomAsset alloc] initWithAsset:result] autorelease];
     [customAsset setParent:self];

     [libraryPhotosAssets addObject:customAsset];
 }]; 


NSLog(@"done enumerating photos");
[tview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

// only do this if I want to re-select some assets
if(assetsToRestore)
{
    for(NSDictionary *dict in assetsToRestore)
    {
        NSIndexPath *indexPathToRestore = [dict objectForKey:@"selectedAssetIndexPath"];
        int tagToRestore = [[dict objectForKey:@"selectedAssetTag"] intValue];
        [self selectAssetWithIndexPath:indexPathToRestore andIndex:tagToRestore];
    }
}

[pool drain]; }
4

1 に答える 1

0

私が間違っている場合は修正してください。自動解放プールの使用は、次のようにする必要があると思いました。

@autoreleasepool {
    (statements)
}

それは私のために働いた。

于 2012-10-03T15:16:13.743 に答える