我有一个问题,我在我的应用程序中看到内存使用量攀升(但 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]; }