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

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

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

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

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

2回答

486閲覧

CollectionViewにURLから画像を表示

sam3457

総合スコア52

Firebase

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

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

0クリップ

投稿2018/04/05 05:57

なんどもすみません。。
FirebaseRDBに保存した画像のURLをCollectionViewに表示する処理を書いています。
以下のコードで起動してもcollectionviewには表示されませんでした。

RDBからURLの取得自体ができていないのかと思い、print(画像のURL)で確認してみたのですが、URLは取得できていました。

残るは原因はcellForItemAtのところくらいだと思うのですが自分には何が原因なのかわかりませんでした。

ご存知の方がいらっしゃいましたらよろしくお願いいたします。
イメージ説明

swift

1import UIKit 2import Firebase 3import SDWebImage 4 5class PostList: UICollectionViewController { 6 7 var posts = [NSDictionary]() 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 12 //ログインチェック 13 if UserDefaults.standard.object(forKey: "check") != nil { 14 //何もしない 15 } else { 16 let loginViewController = self.storyboard?.instantiateViewController(withIdentifier: "login") 17 self.present(loginViewController!, animated: true, completion: nil) 18 } 19 20 loadAllData() 21 collectionView?.reloadData() 22 23 } 24 25 @IBAction func loginOrOut(_ sender: Any) { 26 performSegue(withIdentifier: "goLogin", sender: nil) 27 } 28 29 30 //RDBにある投稿画像の参照(URL)を取ってくる 31 func loadAllData() { 32 33 let RDBRef = Database.database().reference().child("posts") 34 RDBRef.queryLimited(toLast: 10).observe(DataEventType.childAdded, with: { (snapshot) in 35 var tempPosts = [NSDictionary]() 36 for post in(snapshot.children) { 37 38 let child = post as! DataSnapshot 39 let dict = child.value 40 tempPosts.append(dict as! NSDictionary) 41 print(tempPosts) 42 } 43 self.posts = tempPosts 44 45 }) 46 47 } 48 49 override func didReceiveMemoryWarning() { 50 super.didReceiveMemoryWarning() 51 } 52 53 /* 54 // MARK: - Navigation 55 56 // In a storyboard-based application, you will often want to do a little preparation before navigation 57 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 58 // Get the new view controller using [segue destinationViewController]. 59 // Pass the selected object to the new view controller. 60 } 61 */ 62 63 // MARK: UICollectionViewDataSource 64 65 override func numberOfSections(in collectionView: UICollectionView) -> Int { 66 return 1 67 } 68 69 70 override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 71 return posts.count 72 } 73 74 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 75 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) 76 77 let dict = posts[(indexPath as IndexPath).row] 78 79 //投稿画像(postimageを表示) 80 let postImageView = cell.contentView.viewWithTag(1) as! UIImageView 81 let postStr = dict["postimage"] as? String 82 let postUrl = URL(string: postStr!) 83 postImageView.sd_setImage(with: postUrl) 84 85 //let iconImageView = cell.contentView.viewWithTag(2) as! UIImageView 86 //let nameLabel = cell.contentView.viewWithTag(3) as! UIImageView 87 88 89 90 91 return cell 92 } 93 94 95} 96

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

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

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

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

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

guest

回答2

0

516kさんのご回答の内容で動作はすると思いますので、1点だけ補足します。

ご質問のコードではメモリリークを起こしてしまっています。
Firebase RDBのデータ監視リスナーはデタッチしなければイベントがずっと送られてくる状態になってしまいますので、 viewDidUnload あたりでデタッチするようにすべきです。

参考: 公式ドキュメント

swift

1// コード例 2 3let handle = RDBRef 4 .queryLimited(toLast: 10) 5 .observe(...) { ... } 6 7... 8 9override func viewDidUnload() { 10 super.viewDidUnload() 11 12 // リスナーのデタッチ 13 RDBRef.removeObserver(withHandle: handle) 14}

投稿2018/04/06 04:08

kakajika

総合スコア3131

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

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

sam3457

2018/04/07 08:51

お返事が遅くなって申し訳ありません。 回答ありがとうございます!いつもお世話になっております。 メモリリーク、、動作のことばかり調べたりしていたのでそちらの方は完全に蔑ろになっておりました、、 メモリリークについてはほとんど知識が無かったので、これを機に詳しく調べて他の処理でも意識してみることにします。非常にありがたいです。。 ありがとうございますm(_ _)m
guest

0

ベストアンサー

swift

1collectionView?.reloadData()

のタイミングの問題が気になりました。
上記の質問のコードではおそらく非同期処理にてデータベースにデータを問い合わせ、実際にデータが返ってくる前にcollectionView?.reloadData()が実施されているように見受けられます。

swift

1RDBRef.queryLimited(toLast: 10).observe(DataEventType.childAdded, with: { (snapshot) in 2 var tempPosts = [NSDictionary]() 3 for post in(snapshot.children) { 4 5 let child = post as! DataSnapshot 6 let dict = child.value 7 tempPosts.append(dict as! NSDictionary) 8 print(tempPosts) 9 } 10 self.posts = tempPosts 11 self.collectionView?.reloadData() 12 })

このようにメソッドの完了時クロージャ内でデータをpostsにセットした後にreloadData()したらどうなりますでしょうか?

投稿2018/04/05 08:45

516k

総合スコア189

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

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

516k

2018/04/05 08:46

この完了時クロージャがメインスレッドでない場合は、メインスレッドにDispatchしてreloadData()して下さい。
sam3457

2018/04/07 08:31

お返事が遅くなってしまい申し訳ありません。 回答ありがとうございます! 非同期処理でデータが帰ってくる前にcollectionView?.reloadData()が呼ばれていたのですね、、 それを防ぐためにクロージャ内でreloadData()を呼ぶ必要があったのですね! 515k様にお教えいただいた様に、メソッドの完了時クロージャ内でデータをpostsにセットした後にreloadData()をすることでcollectionviewに表示される様になりました! ありがとうございますm(_ _)m もう一つお聞きしたいのですが、投稿画像は違うものを複数投稿していたはずなのですが表示される画像は全部同じものになっていました。。 postsに入れるURLが全部同じになってしまっているか、cellForItemAt内で最初のURLだけを何個も表示しているのかだと思ったのですが、自分にはどちらも異常ない様に見えてしまいます、、 質問のコードから516k様の回答のご指摘部分以外は変えていないのですが、もしよろしければそちらの方もご覧いただけると幸いです。
516k

2018/04/07 08:41

let dict = posts[(indexPath as IndexPath).row] のIndexPathのキャストは何の意味がありますかね?ひょっとしたらここで毎回ゼロが返ってきてるかもしれません。
sam3457

2018/04/07 09:01

少し前に普通にこの様に let dict = posts[indexPath.row] 記述したらなぜか画面が真っ白になって、いろいろ試しているうちにキャストをして普通に画面が表示される様になったのですが、 今、キャストを解いて let dict = posts[indexPath.row] で起動してみたのですが今度はちゃんと表示されました、、笑 多分違う部分の修正の効果をそこの効果と勘違いしてその様に記述していたものと思われます、、 let dict = posts[indexPath.row] に直して起動してみた結果なのですが、先ほどと同じく同じ画像がずらっと並んでいました、、
sam3457

2018/04/07 09:14 編集

分かり難かったかもしれないので一応、 let dict = posts[indexPath.row]に直して起動してみた結果はやはり同じ画像がずらっと表示されていました。 ということです!
516k

2018/04/07 12:12

今回のviewはtableではなくてcollectionなので、indexPath.rowではなくてindexPath.itemではいかがでしょう?
sam3457

2018/04/07 14:01

今、.itemで確認してみたのですがやはり結果は同じでした、、 posts配列の中身が同じになっているのかなとも思ったのですが、print()で確認してURLが違うことを確認していますし、それもないですよね、、
516k

2018/04/07 14:19

質問を立て直した方がいいと思いますが、 let dict = posts[(indexPath as IndexPath).row] と let dict = posts[indexPath.item] の結果が同じなのですか? その場合 let postUrl = URL(string: postStr!) print(postUrl) の表示結果も全く同じでしょうか。
sam3457

2018/04/08 06:07

let dict = posts[(indexPath as IndexPath).row] と let dict = posts[indexPath.item] の結果は同じでした。 print(postUrl)の表示結果は異なるURLがpostsの数分だけコンソールに表示されました。 そうですね、、申し訳ありません。 質問を立て直してみます。 最後までありがとうございますm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問