0

現在、多くの画像を含む UICollectionView に取り組んでいます。ただし、このビューではメモリ警告でクラッシュすることがあります。AFNetworking および UIImageView+AFNetworking カテゴリを使用して、 setImageWithURL: メソッドで画像を設定しています。1 つの問題はキャッシングです。AFNetworking が画像キャッシュを処理するかどうかはわかりません。とにかく、メモリ管理の観点からこのコードを最適化する方法はありますか? または、このビュー コントローラーに didReceiveMemoryWarning メソッドを実装する場合、このメソッドには何を入れることができますか? このコレクション ビューの cellForItemAtIndexPath のコードを添付します。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"RecipeCell" forIndexPath:indexPath];

// setting the image view for the cell using AFNetworking. Does this do caching automatically?
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:6];
if (PRODUCTION) {
    [recipeImageView setImageWithURL:[[self.recipes objectAtIndex:indexPath.row] objectForKey:@"recipe_image"] placeholderImage:[UIImage imageNamed:@"default_recipe_picture.png"]];
} else {
    [recipeImageView setImageWithURL:[NSString stringWithFormat:@"http://localhost:5000/%@", [[self.recipes objectAtIndex:indexPath.row] objectForKey:@"recipe_image"]] placeholderImage:[UIImage imageNamed:@"default_recipe_picture.png"]];
}


// configure the back of the cell. fill all the info.
UITextView *recipeNameView = (UITextView *)[cell viewWithTag:8];
recipeNameView.text = [NSString stringWithFormat:@"%@", [[self.recipes objectAtIndex:indexPath.row] objectForKey:@"recipe_name"]];

UILabel *recipeNameLabel = (UILabel *)[cell viewWithTag:2];
recipeNameLabel.text = [NSString stringWithFormat:@"%@", [[self.recipes objectAtIndex:indexPath.row] objectForKey:@"recipe_name"]];

NSDictionary *user = [[self.recipes objectAtIndex:indexPath.row] objectForKey:@"user"];
UIButton *chefNameButton = (UIButton *)[cell viewWithTag:3];
[chefNameButton setTitle:[NSString stringWithFormat:@"%@ %@", [user objectForKey:@"first_name"], [user objectForKey:@"last_name"]] forState:UIControlStateNormal];

NSMutableArray *missingIngredientsStringArray = [[NSMutableArray alloc] init];
NSArray *missingIngredients = [[self.recipes objectAtIndex:indexPath.row] objectForKey:@"missing_ingredients"];
for (NSDictionary *missingIngredient in missingIngredients) {
    [missingIngredientsStringArray addObject:[missingIngredient objectForKey:@"name"]];
}
NSString *missingIngredientsString = [missingIngredientsStringArray componentsJoinedByString:@","];

UITextView *missingIngredientsView = (UITextView *)[cell viewWithTag:4];
missingIngredientsView.text = [NSString stringWithFormat:@"%u Missing Ingredients: %@", missingIngredients.count, missingIngredientsString];

// configure the front of the cell. chef name button and missing ingredients and likes on front view
UIButton *frontNameButton = (UIButton *)[cell viewWithTag:11];
[frontNameButton setTitle:[NSString stringWithFormat:@"%@ %@", [user objectForKey:@"first_name"], [user objectForKey:@"last_name"]] forState:UIControlStateNormal];
[frontNameButton sizeToFit];
frontNameButton.frame = CGRectMake(160 - [frontNameButton.titleLabel.text sizeWithFont:[UIFont boldSystemFontOfSize:13]].width - 7, frontNameButton.frame.origin.y, frontNameButton.frame.size.width, frontNameButton.frame.size.height);

UILabel *likesLabel = (UILabel *)[cell viewWithTag:9];
likesLabel.text = [NSString stringWithFormat:@"%@ likes", [[self.recipes objectAtIndex:indexPath.row] objectForKey:@"likes"]];

UIButton *missingIngredientsButton = (UIButton *)[cell viewWithTag:12];
[missingIngredientsButton setBackgroundImage:[UIImage imageNamed:@"badge_green.png"] forState:UIControlStateSelected];
if (missingIngredients.count == 0) {
    missingIngredientsButton.selected = YES;
    [missingIngredientsButton setTitle:@"" forState:UIControlStateNormal];
} else {
    missingIngredientsButton.selected = NO;
    [missingIngredientsButton setTitle:[NSString stringWithFormat:@"%u", missingIngredients.count] forState:UIControlStateNormal];
}

// make back view invisible.
UIView *backView = [cell viewWithTag:1];
UIView *frontView = [cell viewWithTag:5];
frontView.alpha = 1.0;
backView.alpha = 0;

// adding flip gesture recognizers
UIView *flipView1 = [cell viewWithTag:12];
UIView *flipView2 = [cell viewWithTag:1];

UITapGestureRecognizer *flipGestureRecognizer1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(flipCell:)];
UITapGestureRecognizer *flipGestureRecognizer2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(flipCell:)];
[flipView1 addGestureRecognizer:flipGestureRecognizer1];
[flipView2 addGestureRecognizer:flipGestureRecognizer2];

return cell;
}

[編集] Instruments の実行のスクリーンショットを添付します。 ここに画像の説明を入力

セグエを押して戻るボタンを繰り返し押すと、メモリ割り当てが増加することがわかります。増え続けているのは、CFData、CALayer、CABackingStore、UITableView です。これらはセグエの後に作成されたものではないかと思いますが、リリースされていません...助けてください!

4

2 に答える 2

1

画像の再ダウンロードを避けるために、何らかの画像キャッシュ戦略が必要になるでしょう。また、UIImageView+AFNetworkingカテゴリは画像をキャッシュします。ただし、メモリ内の URL キャッシュに応答がキャッシュされている場合もあります。この場合、これは多少冗長です。

そのため、メモリ内 URL キャッシュを減らすかオフにすることを検討してください。あなたが説明している問題がありましたが、次のことでメモリの問題がかなり軽減されました。

NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
于 2013-06-08T21:48:54.113 に答える
0

AFNetworking は自動的に画像をNSCacheコレクションに保存します。これにより、メモリ不足の警告が発生すると、メモリから画像の一部またはすべてが自動的に削除されます。AFNetworking はおそらくあなたの問題ではありません。

実際、大量の非常に大きな画像をダウンロードして同時に表示しない限り、画像の表示は問題ではないと思います。(この場合は、サイズを変更する必要がないように、デバイスでの表示用に画像を最適化する必要があります。)

私が見る 1 つの問題は、セルがビューに入るたびにジェスチャ認識エンジンをセルに追加していることですが、セルは再利用されるため、セルが再び入ってくると不要なジェスチャ認識エンジンを追加していることです。これは、UITableViewCell をサブクラス化し、ジェスチャ認識機能をプロパティとして割り当てることで解決できます。追加する前にジェスチャ レコグナイザーがアタッチされているかどうかを確認することflipView1で、これを解決することもできます。flipView2(ただし、これがメモリ警告を引き起こすのに十分かどうかはわかりません。)

Build -> Profile に移動し、Allocations インストゥルメントを選択することをお勧めします。左側で、Objective C のみを選択し、システム コールを非表示にします。次に、コレクション ビューをスクロールし、インストゥルメントを見て、すべてのメモリを占有しているものを確認します。

アップデート

以下は、割り当てツールのスクリーンショットです。

ここに画像の説明を入力

于 2013-06-08T21:07:21.213 に答える