こんにちは!🐶
今まではデータの送信について学んできましたが、今回はデータの呼び出しについて学んでいきます!
#下準備
今回は、以前Postコレクションに送ったデータを、タイムライン画面に呼び出します!
そのために、以前作ったタイムライン画面にtableViewを配置しましょう!
今回は、tableViewのcell をカスタムセルにするので、新しくカスタムセルのクラスとstorybordを作ります!作り方はFile作成時にSubclass ofをUITableViewCellに設定しましょう!そして、storybordも作りたいので、Also create XIB fileにチェックを入れてください!
これでカスタムセル が作れました!
そして作ったカスタムセル (TableViewCell)をこのようなデザインにしてください!👇
ユーザー画像のimageViewとユーザネームのlabel,投稿画像のimageViewと投稿内容のtextViewを配置してます!👇
そして,viewControllerにtableVireの設定と前回同様必要なものをimportし、Firestoreのデータベースの変数も作ってあげましょう!👇
import UIKit
import Firebase
import FirebaseAuth
class ViewController: UIViewController {
@IBOutlet var timelineTableView : UITableView!
//Firestoreのデータベース
let db = Firestore.firestore()
override func viewDidLoad() {
super.viewDidLoad()
//tableviewの設定
timelineTableView.delegate = self
timelineTableView.dataSource = self
timelineTableView.register(UINib(nibName: "TimelineTableViewCell", bundle: nil), forCellReuseIdentifier: "Cell")
}
func loadPost() {
}
}
//tableVIewの設定
extension ViewController : UITableViewDelegate,UITableViewDataSource {
//tableViewのcellの数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//postArrayに入れた配列の数だけセルを表示
return postArray.count
}
//tableViewCellの中身
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = timelineTableView.dequeueReusableCell(withIdentifier: "Cell") as! TimelineTableViewCell
cell.postTextView.text = postArray[indexPath.row].postText
return cell
}
//tablaViewの高さ設定
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 500
}
}
今回はカスタムセルを使っているので、TabaleViewCellにも以下のように設定を行います!
class TimelineTableViewCell: UITableViewCell {
@IBOutlet var postTextView : UITextView!
@IBOutlet var userNameLabel : UILabel!
@IBOutlet var userImageView : UIImageView!
@IBOutlet var postImageView : UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
あともう一つの準備として、Nukeというライブラリをpodにinstallしましょう!
これは、あとでPostコレクションから持ってきたURLをNukeを使って、画像に変換するのに使います!
以下をpodに記入しinstallしてください!
pod 'Nuke'
#データを呼び出そう!
それでは、早速データ呼び出しのコードを書いていきたいと思います!
まず初めに流れを説明すると、
1データを呼び出す
2呼び出したデータを配列に入れる
3配列の情報をtableviewに表示する
この順番でいきたいと思います!
では、最初にデータを呼び出しましょう!
データを呼び出す関数を書き、その中でデータを呼び出します!
呼び出し方は以下になります。👇
func loadPost() {
//日付が古いものを下にして持ってくる
db.collection("Post").order(by: "date").getDocuments { (result, error) in
if error != nil {
print("データ呼び出し失敗")
} else {
print("データ呼び出し成功")
}
}
}
まず,今回のタイムラインのように複数の情報(投稿)を持ってきたい時は、db.collection("Post").getDocumentsと表します。単一の情報を取得したい時はdb.collection("Post").getDocument(getDocumentsのsが無い)となります!
これで、resultの中にデータが入りました!
#呼び出したデータを配列の中に入れる
では次は、呼び出したデータをタイムラインのtableViewに表示させるには、配列を用意しその配列の中にデータを入れてあげなければなりません。
ですので、配列を用意するのですが、その前に、持ってきた情報を入れる用の構造体を作りましょう!
構造体とは、複数ある値をセットで保管できるものになります。
例えば、今回で言うと、Postコレクションからデータを持ってくるのですが、持ってくる情報は、テキストや画像など複数あります。それを構造体なしに持ってこようとすると、テキスト用の配列を用意して、画像用の配列を用意して。。。。ととても、面倒なものになってしまいます。
構造体を使うことで、1つの配列だけでで複数の情報を持ってくることができます!
では実際に構造体を作ってみましょう!
作り方はFile作成時 swiftfile >Nextを選択し、名前をPostとして保存しましょう。
すると新しくファイルができました。この中に、Postコレクションから持ってきたい情報を書いていくとこんな感じになります👇
import Foundation
struct Post {
let userImage: String
let userName : String
let postText : String
let postImage : String
let userId : String
}
これで構造体はできました!
そして、これを使い、配列の中にデータを入れていきましょう!
まず、コードは以下になります
db.collection("Post").getDocuments { (result, error) in
if error != nil {
print("データ呼び出し失敗")
} else {
print("データ呼び出し成功")
if let documents = result?.documents {
//配列の初期化
self.postArray = []
//持ってきたデータを一つ一つ配列に入れる
for document in documents {
let data = document.data()
let post = Post(postText: data["text"] as! String, postImage: data["imageUrl"] as! String,userId:data["userId"] as! String)
//古いものを下にする
self.postArray.reverse()
//postArray配列に追加
self.postArray.append(post)
}
}
}
}
}
ここは考えるというよりはやり方を覚えてもらう感じでOKです。説明すると、先ほど作った構造体Postに従って、データを持ってきます。””はFiretoreのドキュメントの中のフィールド名を指します。👇
こうすることで投稿内容と投稿の画像を持ってくることができました!
#tabaleViewに表示させよう!
情報が持って来れたら次はtableViewに表示させましょう!では,extensionでtableViewの設定を行いましょう!👇
extension ViewController : UITableViewDelegate,UITableViewDataSource {
//tableViewのcellの数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//postArrayに入れた配列の数だけセルを表示
return postArray.count
}
//tableViewCellの中身
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = timelineTableView.dequeueReusableCell(withIdentifier: "Cell") as! TimelineTableViewCell
cell.postTextView.text = postArray[indexPath.row].postText
return cell
}
}
こうすることで、cellのpostTextViewには投稿内容が入りました!
では、次は画像を呼び出しましょう!
呼び出す画像は投稿画像とユーザー画像になります!ここで先ほど、podに入れたNukeを使うのでimportしておいてください!
最初に完成形を見せます!👇
//tableViewCellの中身
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = timelineTableView.dequeueReusableCell(withIdentifier: "Cell") as! TimelineTableViewCell
cell.postTextView.text = postArray[indexPath.row].postText
//投稿画像をセルに配置
//Nukeを使いURLから画像に変更してセルのimageUrlに入れる
let imageUrl = URL(string: postArray[indexPath.row].postImage)
Nuke.loadImage(with: imageUrl as! ImageRequestConvertible , into: cell.postImageView)
//ユーザー画像をセルに配置
db.collection("Users").document(postArray[indexPath.row].userId).getDocument { (result, error) in
if error != nil {
print("ユーザー情報取得失敗")
}
print("ユーザー情報取得成功")
let data = result!.data()
let user = User(userName: data!["userName"] as! String, profileImage: data!["profilrImage"] as! String, introduction: data!["introduction"] as! String)
cell.userNameLabel.text = user.userName
//ユーザー画像が設定されていれば
if let userImageUrl = URL(string:user.profileImage ?? "") {
Nuke.loadImage(with: userImageUrl, into: cell.userImageView)
}
}
return cell
}
分解して解説すると、まず投稿用の画像を持ってくるときはこのように書きます。👇
//tableViewCellの中身
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = timelineTableView.dequeueReusableCell(withIdentifier: "Cell") as! TimelineTableViewCell
cell.postTextView.text = postArray[indexPath.row].postText
//Nukeを使いURLから画像に変更してセルのimageUrlに入れる
let imageUrl = URL(string: postArray[indexPath.row].postImage)
Nuke.loadImage(with: imageUrl , into: cell.postImageView)
}
}
Nukeで以前保存したPostコレクションの中にあるimageをURLから画像に変換し、それをセルのimageViewに入れています。
次に、ユーザー画像を持ってきましょう。このようになります👇
//tableViewCellの中身
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//投稿画像を持ってくるコード
//ユーザー画像をを持ってくる
//ユーザーコレクションからドキュメントか投稿した人のユーザーIDと一致するものを持ってくる
db.collection("Users").document(postArray[indexPath.row].userId).getDocument { (result, error) in
if error != nil {
print("ユーザー情報取得失敗")
}
print("ユーザー情報取得成功")
let data = result!.data()
//Userモデル(構造体)を作り、その中に値を入れる
let user = User(userName: data!["userName"] as! String, profileImage: data!["profilrImage"] as! String, introduction: data!["introduction"] as! String)
cell.userNameLabel.text = user.userName
//ユーザー画像が設定されていれば
if let userImageUrl = URL(string:user.profileImage ?? "") {
Nuke.loadImage(with: userImageUrl, into: cell.userImageView)
}
}
return cell
}
となります!ですので、ユーザ画像を持ってくる際は、新しくUserモデル(構造体)を作りましょう!作り方は以前説明した通りで、まず、File作成時 swiftfile >Nextを選択し、名前をUserとして保存しましょう。
その中に持ってきたいユーザー情報を書きましょう👇
struct User {
let userName: String
let profileImage : String
let introduction : String
}
こうする事で、ユーザー情報を持ってくる際にこのUserモデルを使うことによって、簡単に欲しい情報を格納することができます!
はい!では、今まで作ってきたものを関連づけしたら、このようにタイムラインに投稿が表示されましたーー!!!
#お疲れ様でした!
今回は、データ情報を持ってくるということをしました!
これでFirestoreの基本的な機能は実装することができたと思います!8888
まだユーザー画像は設定してないので空白の状態です。
ですので、次回は、ユーザープロフィール編集、つまりデータの更新についてやっていきます!