質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

UITableViewCellがメモリーリークしてしまう

受付中

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 3,152

cherish

score 50

UITableVIewCellがメモリーリークを起こしてしまい困っています。
cellの使い方としては、ググるとよくでてくるような一般的な使い方だと思います。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {        
        let cell: LocationFeedTableViewCell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! LocationFeedTableViewCell

  (省略)

        return cell
    }

症状としては、テーブルをスクロールするたびにメモリが溜まり続けていってしまいます。
希望としては、cellの再利用のタイミングや画面外に外れたタイミングでメモリーを解放して欲しいのですが、うまくいきません。
何か良い方法をご存知の方がいましたら、ご教示いただけるとありがたいです。
よろしくお願いいたします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Stripe

    2015/11/23 23:16

    なぜ、メモリリークしているのがUITableViewCellだと分かったのですか?

    キャンセル

  • cherish

    2015/11/24 06:57

    たしかに、そう言われると確証は持てないですね。TableViewをスクロールするとメモリが増え続けるため、TableVIewCellのせいだと考えていますが、他の部分が原因となっている可能性も捨てずに調べてみたいと思います。

    キャンセル

回答 2

0

よくあるのは、その「(省略)」となっているコードの中でボタン等の部品をaddSubviewでセルに貼り付け、セルを再利用するたびに、以前にaddSubviewした部品を削除しないでどんどんaddSubviewで重ね貼りしてしまうケースだと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/24 23:17

    アドバイスありがとうございます。下記のようにcellを再利用する際に、viewを取り除く処理を加えたところ、かなり改善されました。

    let subviews = self.subviews
    for subview in subviews {
    subview.removeFromSuperview()
    }

    しかし、依然としてスクロールを行うとメモリが増え続ける症状が続いています。
    何箇所かコメントアウトしながら調べたところ下記のような感じでcellの中で動画を再生させているのですが、そちらでメモリの未開放が起こっているようです。

    let fileURL = NSURL(string: feedValues.movieUrl!)
    let avAsset = AVURLAsset(URL: fileURL!, options: nil)
    playerItem = AVPlayerItem(asset: avAsset)
    let movieView: UIView = UIView()
    movieView.frame = CGRectMake(0, 0, myBoundSize.width, myBoundSize.width)
    videoPlayer = AVPlayer(playerItem: playerItem)
    videoPlayer.muted = true
    let videoPlayerView = AVPlayerView(frame:CGRectMake(0, 0, myBoundSize.width, myBoundSize.width))

    let layer = videoPlayerView.layer as! AVPlayerLayer
    layer.videoGravity = AVLayerVideoGravityResizeAspect
    layer.player = videoPlayer
    videoPlayer.play()


    movieView.layer.addSublayer(layer)
    self.addSubview(movieView)

    キャンセル

  • 2015/11/25 01:28

    もしかして、各セル毎にAVPlayerとAVPlayerLayerを生成し、
    全てを同時再生しているのでしょうか?
    全てを同時再生しているのだったら、各動画の音声も同時出力
    されて聞き取れなくなると思うのですが、このあたりはやはり
    同時には1個だけの再生になるようどこかで制御しているのでしょうか?

    そのあたりをどう制御しているかよく見えませんが、
    特に何もしてないのだったら、セルが再利用待ちの間もずっと
    動画再生は生きており、再利用待ちセルがたまるのと比例して
    消費メモリも増えると思います。
    そのあたりを見直すとよいように思えました。

    ちなみに、同様のことをしている有名アプリとしてVineがありますが、
    Vineでは同時に再生される動画は1個で、音声もその再生中の動画だけ
    音声が流れますよね。

    キャンセル

  • 2015/11/25 10:22

    度々ご回答いただき誠にありがとうございます。
    動画を一つづつしか再生しない処理を入れているのですが、それを取り除いたところ、全ての動画が再生されてしまい、スクロールするごとに再生される動画が増えてしまっています。
    cellの再利用時にAVPlayerがうまく削除されていないようです。
    AVPlayerを削除する方法を考えてみます。

    キャンセル

-2

回答ではなく同様の問題で困っております。
私はUITableViewCellを継承してカスタムセル(MATableViewCell)を作っております。
ビューはxibで定義しています。
MATableViewCellにinitCellというメソッドを定義しており、
セル表示データを更新しています。
引数も参照渡しにし、特に大きなオブジェクトは作成しないように気をつけているにもかかわらず、
keima様と同様の問題が起きて困っております。
このinitCellを呼び出さないとメモリは増えません。
cell内のビューが多重に生成されているのでしょうか。。。
    // セルデータ初期化
    internal func initCell(inout men: Men) {
        if iconImage != nil && men.image1 != nil {
            iconImage!.image = men.image1
        }
        shopName.text = men.shopname
        katasaMeter.setProgress(Float(men.katasa) / 10.0 + 0.05, animated: false)
        katasaScore.text = String(men.katasa)
        kosaMeter.setProgress(Float(men.kosa) / 10.0 + 0.05, animated: false)
        kosaScore.text = String(men.kosa)
        aburaMeter.setProgress(Float(men.abura) / 10.0 + 0.05, animated: false)
        aburaScore.text = String(men.abura)
        //visitDate.text = Utils.formatPickerDateTime(men.date!, style: "y-M-d")
        memo.text = men.memo
        score.setScore(men.score)
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/27 13:26

    initCellを呼び出さないようにするとメモリが増えないのであれば、今度はそのinitCell内の各行を少しずつ削除して行って、どこでメモリが増えなくなるか調べれば、なにかわかるのではないでしょうか?
    元の質問と同じ現象に見えたとしても、やっていることが全く違うのですから、その調べ方も原因も違うはずです。解決しないようなら、ちゃんと新たに質問をたてた方がよいと思います。ここで回答エリアに便乗質問を入れても、見ているのは元の質問者とここに回答を入れている回答者くらいです。
    また、新たに質問を立てる場合、initCellメソッドの内容だけでなく、MATableViewCellクラス全体や、そのMATableViewCellを使っている場所の処理を説明した方がよいと思います。
    そもそも「使用メモリが増えている」のが、どれくらい増えていて、どうおかしいのかも具体的に示さないと、セルが再利用待ちの間に保持されている分が増えただけじゃないですか?という回答になりかねません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る