我有一个问题,我在我的应用程序中看到内存使用量攀升(但仪器中没有明显的泄漏)。
我有一个带有两个viewControllers的测试项目:MainViewController和PhotoViewController。 MainViewController包含一个按钮,只需通过uinavigationcontroller pushViewController方法推送PhotoViewController。
在PhotoViewController中,我使用ALAssetsLibrary用图像填充UITableView。我基本上分两部分做这件事。首先,我检查看看哪些assetGroups可用,因为我需要显示来自Camera Roll和Photolibrary的图像。完成后,我调用另一种方法来枚举实际的资产。
这是一个奇怪的行为:如果我按下PhotoViewController并让它完成整个枚举并填充UITableView,然后弹出回MainViewController,一切都很好。
然而,如果我反复快速地推出并弹出PhotoViewCOntroller(虽然它还没有完成枚举和填充UITableiew),那么我看到我的内存使用量逐渐攀升,直到应用程序最终死亡。我没有看到仪器中有任何明显的泄漏。
我不知道相关代码,但这里有两个用于枚举的方法。当然,在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]; }
答案 0 :(得分:0)
纠正我,如果我错了,我认为使用自动释放池应该是这样做的:
@autoreleasepool {
(statements)
}
这对我有用。