少し使用すると、アプリが遅くなり、で応答しなくなるようですUITableViewController
。かなり集中的な方法がいくつかありますが、これらが実行されると、アプリの全体的なパフォーマンスに影響を与える理由はありません。
私はそれが何であるかを決定するために楽器を使用してきました、しかしそれは非常に決定的ではないことを証明しています。まず、1つの方法で問題を再現することはできません。これは、一般的な使用法から発生しているようです。CPUを使用する主なものは、cellForRowAtIndexPath
スレッドの使用状況に応じたものです。私は実際にかなり多くの計算を行いますが、2つのことを説明していません。1)この問題が時間の経過とともに発生する理由。TableViewController
アプリを最初に起動したときに上下に数回スクロールでき、すべてが非常にスムーズです。2)3つまたは4つのセルを除いてすべて削除しても、無反応が残ります。
もう1つの観察結果はmodal ViewController
、アプリが最初に読み込まれたときのアニメーションは非常にスムーズですが、後でこの恐ろしいギザギザのアニメーションが発生することもあります。繰り返しになりますが、このモーダルの却下(managedObjectContext保存を含む)にはかなり複雑な計算がいくつかあり、UITableView
その下(いくつかを意味するcellForRowAtIndexPath
)を明らかにするのに近いですが、これら2つのことだけでアニメーションを仮想的に実現する方法はありません0fps。これらすべてのことから、私はリソースが使い果たされて戻ってこないのだと信じるようになりました。残念ながら、iOS環境については、次の前提条件を確認するのに十分な知識がありませんが、次のようになります。
メモリー。簡単に言えば、これは本当にできませんか?私のアプリは大量の画像を含む非常にメモリを消費しますが、iOSはRAMが不足し始めるとRAMから物を削除すると確信しています。その上、診断では、アプリで大量のラグが発生したときに50MBの空き容量があったことが示されています。
CPU。前回パフォーマンスの問題が発生したとき(メソッドの無限ループを呼び出したとき)のように、何かがCPUをすべて使い果たしている可能性があると思いましたが、アプリは必要な場合にのみCPUを使用しているようです。つまり、アプリがアイドル状態のときは、使用量が0に戻ります。これがいかに重要であるかを説明するためだけに。リソースとしてのCPUが何かに使い果たされていた場合、それはなぜ
cellForRowAtIndexPath
時間の経過とともに苦労していたのかを説明します。ただし、食べ尽くされていないため、アプリを長時間使用cellForRowAtIndexPath
するとCPUの使用量が多すぎる理由はありません。したがって、CPUが占有されていることが原因で問題が発生していることがわかりません。
当然のことながら、私が考えることができるのはこれらの2つのリソースだけなので、私は完全にそして完全に困惑しています。なぜアプリが時間の経過とともに遅くなるのかわかりません。実際、アプリが最初に起動したときに正常に動作するため、コードがどのように機能するかがわかりません。また、十分に残っているように見えるときに、どのようにリソースになるかがわかりません。
私はObjective-C/iOSの開発に慣れていないので、何か足りないものがあるのではないかと思います。あなたが私がそれを特定するのを手伝ってくれるなら、私はそれを本当に感謝します。
更新:との私のコードを投稿cellForRowAtIndexPath
するwillDisplayCell
:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
myEntityForConfigureCell = [self.fetchedResultsController objectAtIndexPath:indexPath];
searchResultForConfigureCell = [searchResults objectForKey:myEntityForConfigureCell.trackId];
// Example of how I fill in cell information. There are far more than shown.
nameLabelForConfigureCell = (UILabel *)[cell viewWithTag:1001];
nameLabelForConfigureCell.text = myEntityForConfigureCell.name;
genreLabelForConfigureCell = (UILabel *)[cell viewWithTag:1002];
genreLabelForConfigureCell.text = searchResultForConfigureCell.genre;
// Example of how I do the ImageViews using AFNetworking
imageForConfigureCell = (UIImageView *)[cell viewWithTag:1000];
[imageForConfigureCell setImageWithURL:[NSURL URLWithString: searchResultForConfigureCell.artworkURL60]];
imageForConfigureCell.layer.cornerRadius = 9.4;
imageForConfigureCell.layer.masksToBounds = YES;
// The RateView for showing a start rating
rateViewForConfigureCell = [[DYRateView alloc] initWithFrame:CGRectMake(73, 44, 75, 12) fullStar:[UIImage imageNamed:@"StarFullSmall.png"] emptyStar:[UIImage imageNamed:@"StarEmptySmall.png"]];
rateViewForConfigureCell.rate = [searchResultForConfigureCell.rating floatValue];
rateViewForConfigureCell.alignment = RateViewAlignmentLeft;
[cell.contentView addSubview:rateViewForConfigureCell];
// Setting Sections for all Core Data entries only if BOOL isLoading is YES, but **has** finished downloading informaton, i.e. just before completion.
if ([searchResults count] == [fetchedResultsController.fetchedObjects count]) {
if (isLoading) {
NSLog(@"Is loading so Setting Sections");
isLoading = NO;
[self cycleThroughEntriesAndSetSection];
}
else if (!isLoading){
[loadingHudView removeFromSuperview];
}
}
}
そして今のためにwillDisplayCell
:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
myEntityForDisplayCell = [self.fetchedResultsController objectAtIndexPath:indexPath];
searchResultForDisplayCell = [searchResults objectForKey:myEntityForDisplayCell.trackId];
UILabel *currentPrice = (UILabel *)[cell viewWithTag:1003];
if ([myEntityForDisplayCell.price1 floatValue] == [searchResultForDisplayCell.price2 floatValue]) {
currentPrice.textColor = [UIColor blackColor];
}
else if ([myEntityForDisplayCell.price1 floatValue] > [searchResultForDisplayCell.price2 floatValue])
{
currentPrice.textColor = [UIColor colorWithRed:0 green:0.9 blue:0 alpha:1];
}
else if ([myEntityForDisplayCell.price1 floatValue] < [searchResultForDisplayCell.price2 floatValue])
{
currentPrice.textColor = [UIColor redColor];
}
cell.backgroundColor = nil;
if (isLoading) {
loadingHudView.numOne = [searchResults count];
loadingHudView.numTwo = [fetchedResultsController.fetchedObjects count];
[loadingHudView setNeedsDisplay];
}
if ([searchResults count] == [fetchedResultsController.fetchedObjects count]) {
[loadingHudView removeFromSuperview];
if ([myEntityForDisplayCell.price1 floatValue] < [searchResultForDisplayCell.price2 floatValue]) {
cell.backgroundColor = nil;
}
else
{
cell.backgroundColor = [UIColor colorWithRed:1 green:0.85 blue:0 alpha:0.45];
}
}
}
更新2:アナライザーツールで何かを見つけました。それがどのようにリークであるかは完全にはわかりませんが、とにかくここに行きます。
SearchResult *searchResult = [[SearchResult alloc] init];
for (id i in fetchedResultsController.fetchedObjects) {
MyEntity *myEntity = i;
searchResult = [searchResults objectForKey:myEntity.id];
このコードは、新しいエンティティがCore Dataデータベースに追加されるたびに、つまり特に頻繁に実行されることはないでしょう。