1

我有一个问题,我在我的应用程序中看到内存使用量攀升(但 Instruments 中没有明显的泄漏)。

我有一个包含两个视图控制器的测试项目:MainViewController 和 PhotoViewController。MainViewController 包含一个按钮,它通过 uinavigationcontroller pushViewController 方法简单地推送 PhotoViewController。

在 PhotoViewController 中,我使用 ALAssetsLibrary 用图像填充 UITableView。我基本上分两部分来做这件事。首先,我查看可用的资产组,因为我需要显示来自相机胶卷和照片库的图像。完成后,我调用另一个方法来枚举实际资产。

这是奇怪的行为:如果我推送 PhotoViewController 并让它完成整个枚举并填充 UITableView,然后弹出回 MainViewController,一切都很好。

但是,如果我反复快速地推出并弹出 PhotoViewCONtroller(虽然它还没有完成枚举和填充 UITableiew),那么我会看到我的内存使用量逐渐攀升,直到应用程序最终死掉。我在 Instruments 中没有看到任何明显的泄漏。

我不知道相关代码,但这里有两种用于枚举的方法。当然,在dealloc中,我正在发布相关的ivars。

有没有办法在弹出时取消枚举?

就像一个注释,我的测试代码基于这个项目(https://github.com/elc/ELCImagePickerController),虽然高度定制。但是,我刚刚使用该代码进行了测试,并且发生了同样的问题。请注意,如果您有足够的 ALAsset 进行枚举,您只会看到内存使用量攀升。如果数量太少,那么它会在你弹出之前完成枚举。

谢谢!

- (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 回答