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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2623閲覧

UICollectionViewを縦に高速でスクロールしてたら、メモリ関連のエラーでアプリが強制的に落ちる。

kou009

総合スコア16

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2018/10/10 12:51

編集2018/10/11 05:32

[行いたいこと]
'Message from debugger: Terminated due to memory issue'というエラーメッセージが出て、アプリが落ちるのですが、どのようにしたらエラーを防げますか?

[発生した問題]
UICollectionViewを上下に高速でスクロールしていたらアプリが落ちる

イメージ説明

[エラーメッセージ]
Message from debugger: Terminated due to memory issue

[ストーリーボード]
UICollectionViewを実装し、cellの中にはimageviewとViewとViewの中にラベルが2つ入っています。
イメージ説明

[メモリ]
xcodeのMemoryと書いてあるところをみると、スクロールしてる最中のメモリは、
200MB前後ぐらいから280MB前後ぐらいまでになります。
イメージ説明

[使っているデバイス]
実機のiPhone6

Postクラス

Swift

1class Post { 2 3 var id: String? 4 var timestamp: Int? 5 var imageUrls = [String]() 6 7} 8 9 10extension Post { 11 static func transformPostPhoto(dict: [String: Any], key: String) -> Post { 12 let post = Post() 13 post.id = key 14 post.timestamp = dict["timestamp"] as? Int 15 let image0 = dict["image0"] as? String 16 let image1 = dict["image1"] as? String 17 post.imageUrls.append(image0!) 18 post.imageUrls.append(image1!) 19 return post 20 } 21}

UICollectionViewDataSourceと、UICollectionViewDelegateFlowLayoutを継承したクラス

Swift

1//100個ほど入ってる。 2 var posts = [Post]() 3 4//追記 5override func viewDidLoad() { 6 super.viewDidLoad() 7 8 var REF_POSTS = Database.database().reference().child("posts") 9 REF_POSTS.queryOrdered(byChild: "timestamp").observeSingleEvent(of: .value) { (snapshot) in 10 if let arraySnapshot = (snapshot.children.allObjects as? [DataSnapshot])?.reversed() { 11 12 arraySnapshot.forEach({ (child) in 13 if let dict = child.value as? [String: Any] { 14 let post = Post.transformPostPhoto(dict: dict, key: child.key) 15 16 self.posts.append(post) 17 } 18 }) 19 20 self.collectionView.reloadData() 21 } 22 } 23 } 24 25 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 26 return posts.count 27 28 } 29 30 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 31 { 32 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PostCollectionViewCell", for: indexPath) as! PostCollectionViewCell 33 34 35 cell.post = self.posts[indexPath.item] 36 return cell 37 38 39 } 40 41 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 42 return 2 43 } 44 45 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 46 return 0 47 } 48 49 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 50 return CGSize(width: collectionView.frame.size.width / 2 - 1, height: (collectionView.frame.size.width / 2 - 1) + 76) 51 } 52

Cellのクラス

Swift

1class PostCollectionViewCell: UICollectionViewCell { 2 3 @IBOutlet weak var photo: UIImageView! 4 var savePhotoUrl: URL? 5 6 var post: Post? { 7 didSet { 8 updateView() 9 } 10 } 11 12//修正&追記 13 func updateView() { 14 print("Thread.isMainThread ", Thread.isMainThread) // true 15 print("Thread.current ", Thread.current) //<NSThread: 0x281e91d40>{number = 1, name = main} 16 if let photoUrlString = post?.imageUrls[0] { 17 18 let photoUrl = URL(string: photoUrlString) 19 20 // 読み込み(新規) 21 if savePhotoUrl == nil { 22 self.photo.sd_setImage(with: photoUrl) { (image, error, SDImageCacheType, url) in 23 self.savePhotoUrl = url 24 } 25 } 26 27 // 何もしない(キャッシュ) 28 else if savePhotoUrl == photoUrl { 29 print("何もしない(キャッシュ)") 30 } 31 // キャンセル処理後に読み込み 32 else if savePhotoUrl != photoUrl /*&& 読み込み中*/ { 33 self.photo.sd_setImage(with: photoUrl) { (image, error, SDImageCacheType, url) in 34 self.savePhotoUrl = url 35 } 36 // (必要なら解放処理後に)読み込み 37 else if savePhotoUrl != photoUrl { 38 39 } 40 41 // if self.savePhotoUrl == photoUrl { 42 43 // self.photo.sd_setImage(with: photoUrl) 44 // } else { 45 // print("一致しないので読み込みキャンセル") 46 // } 47 } 48 } 49} 50

メモリ関連のエラーであることはわかるのですが、
何が原因(ストーリーボードなのかコードなのかそれ以外なのか)でアプリが落ちてるのかわかりません。どなたかご教授いただけたら幸いです。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2018/10/11 00:11

まずは画像の読み込みをやめて落ちるかどうかの確認ですね。で、非同期で画像を読み込んでいるんだと思いますが、読み込んでいる最中に再度リクエストされることは想定していますか?(キャンセル処理が出来ているかどうか、など)言い換えると、セルの再利用は考慮されていますか?ということです。
kou009

2018/10/11 01:38 編集

ありがとうございます。画像の読み込みをやめてみるとアプリは落ちなくなりました。スクロールしてもメモリは、50から60MB程度に下がりました。 キャンセル処理についてですが、合ってるか自信ないですが書いてみました。質問文の方を修正いたします。でも、まだMessage from debugger: Terminated due to memory issueとエラーが出てアプリがおちてしまいます。
guest

回答1

0

ベストアンサー

追記修正欄では書きづらいのでこちらに書きます。

savePhotoUrlが、

  • nil → 読み込み(新規)
  • == photoUrl → 何もしない(キャッシュ)
  • != photoUrl&読み込み中 → キャンセル処理後に読み込み
  • != photoUrl&読み込み済 → (必要なら解放処理後に)読み込み

みたいな感じになると思うのですが。

Postってライブラリでしょうか?
まともなライブラリなら、この辺は勝手にやってくれそうな気もしますが‥。

投稿2018/10/11 02:15

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kou009

2018/10/11 03:07

Postクラスは自作のカスタムクラスになります。質問本文に追記いたしました。あと、UICollectionViewDataSourceを継承したクラスのviewDidLoad()も追記いたしました。viewDidLoadで、データベースからデータをとってきて、var posts = [Post]()にappendしています。あと、僕が書いたsavePhotoUrlの変数に値を入れるタイミングは合ってるでしょうか?回答いただき、書き直しましたが、画像が表示されなくなってしまいました。
fuzzball

2018/10/11 04:15 編集

>>savePhotoUrlの変数に値を入れるタイミング 判定する前に上書きしちゃったらダメでしょう。 【編集】後半削除しました。
kou009

2018/10/11 05:15

確かにこれだと意味ないですね。失礼しました。setImageのcompletionBlockで入れるということですかね。やってみます。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問