iPhone でコア データが多くのメモリを消費するという問題があります。開始時に、次のように fetchrequest を設定します。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tweets" inManagedObjectContext: [[ChubbyEyetwitterEngine sharedInstance] getManagedObjectContextForUse]];
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"isWatchList==NO && favorited == NO && accountHolder.id_str == %@ ",[[ChubbyEyetwitterEngine sharedInstance] getActiveUserID]];
// Define how we will sort the records
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:[sortTweetaryTimeLine objectForKey:@"sortKey"] ascending:[[sortTweetaryTimeLine objectForKey:@"ascending"] boolValue]] autorelease];
NSSortDescriptor *secondarySortKey = [[[NSSortDescriptor alloc] initWithKey:@"created_at" ascending:FALSE] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObjects:
sortDescriptor,
secondarySortKey,nil];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
[request setPredicate:predicate];
[request setSortDescriptors:sortDescriptors];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
//smaller batch on iphone
[request setFetchBatchSize:12];
}else {
//bigger on the ipad
[request setFetchBatchSize:100];
}
//prefetching important relationships to cache data
[request setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObjects:@"ownerOfThisTweetary",@"thisEntity", nil]];
diaryFetchResultsController= [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[[ChubbyEyetwitterEngine sharedInstance] getManagedObjectContextForUse] sectionNameKeyPath:[sortTweetaryTimeLine objectForKey:@"sectionName"] cacheName:nil] ;
NSError *fetchError = nil;
if ([diaryFetchResultsController performFetch:&fetchError]) {
}else
{
}
diaryFetchResultsController.delegate = self;
この後、タブビューで reloadData を呼び出します。テーブルビューでは、テキスト プロパティの長さとマネージド オブジェクトの他のプロパティに基づいてセルの高さを動的に計算し、高さを返します。
ここでの問題は、リロード データの呼び出し時に、fetchedresultscontroller 内のすべてのオブジェクトが呼び出された heightforrow を持つことです。これにより、オブジェクトがメモリにフォールトします。現在、テーブルビューには数百に及ぶ多くのオブジェクトがあり、メモリ消費量が急増しています。
メモリを節約する方法を探しています:
試したこと: [diaryFetchResultsController.managedObjectContext setStalenessInterval:2.0]; これは何の効果もありませんでした、または少なくとも私が見ることができる効果があったので、私は何か他のことを試しました->
heightForRowAtIndexPath 内で、高さを計算した後、[diaryFetchResultsController.managedObjectContext refreshObject:object mergeChanges:YES]; を試しました。結果は悪く、無限ループに陥りました。実際に起こっていたのは、オブジェクトに障害が発生した場合、システムはそのインデックスパスに対して heightForRowAtIndexPath を自動的に呼び出すということです。
私の 2 番目の試みは、refresh オブジェクトを heightForRowAtIndexPath から削除し、代わりに cellForRowAtIndexPath の最後に挿入することでした。上記と同じ結果です。
私の3回目の試み::
-(void) turnMeBackIntoAfault{
for (id object in diaryFetchResultsController.fetchedObjects){
[diaryFetchResultsController.managedObjectContext refreshObject:object mergeChanges:YES];
}
}
次に、テーブルビューで reloadData を呼び出した直後にこのメソッドを呼び出します。その結果、すべてのセルに対して heightForRowAtIndexPath が 1 回呼び出され (予想どおり)、すべての manageobjects で turnMeBackIntoAfault が呼び出されました。ただし、悪いニュースは、システムがすべてのセルに対して heightForRowAtIndexPath を再度呼び出した直後に、オブジェクトをフォールトに戻す効果を無効にすることです。また、フォールトの前に tableveiw デリゲートとデータソースを nil に設定し、fetchedresultscontroller デリゲートを nil に設定して、ループ後に再度自分自身に戻そうとしましたが、効果は同じです。
これで、heightForRowAtIndexPath が大量のメモリ消費を引き起こしていることは間違いありません。コメントアウトされた heightForRowAtIndexPath を試してみたところ、使用可能なメモリの空き容量がほぼ 1.5 倍になりました。
動的な行を持つことは私のアプリにとって不可欠であり、私のアプリケーションが fetchedresultControllers と tableview を多用しているため、メモリ不足の状態に陥っています。
メモリを節約するための助けをいただければ幸いです。私はこれについて一日中頭を悩ませてきました