アプリでメモリ使用量が上昇している (ただし、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]; }