【Swift】リアルタイムチャットを実現するFirebaseでCRUD(データ作成、読み込み、更新、削除)をやってみる
こちらを参考にログイン機能ありのTODOアプリを作成しました。
今回学んだのはユーザー情報と投稿情報の紐付け方です。
自分なりの理解をコメントに入れています。
#ユーザー情報と投稿情報の紐付け方
func create() {
//textFieldになにも書かれてない場合は、その後の処理をしない
guard let text = textField.text else { return }
//ロートからログインしているユーザーのIDをchildにしてデータを作成
//childByAutoId()でユーザーIDの下に、IDを自動生成してその中にデータを入れる
//setValueでデータを送信する。第一引数に送信したいデータを辞書型で入れる
//今回は記入内容と一緒にユーザーIDと時間を入れる
//FIRServerValue.timestamp()で現在時間を取る
self.ref.child((Auth.auth().currentUser?.uid)!).childByAutoId().setValue(["user": (Auth.auth().currentUser?.uid)!,"content": text, "date": ServerValue.timestamp()])
//テスト表示
print("user\((Auth.auth().currentUser?.uid)!)content\(text)date\(ServerValue.timestamp())")
}
一般的にFirebaseでデータを保存するときは、setValue
で行いますが、今回はunique-post-id
などを生成するためにchildByAutoId
を使いました。おそらく。
メソッド | 一般的な使用例 |
---|---|
setValue | users/user-id/username など、定義済みのパスへのデータの書き込みや、データの置換を行います。 |
childByAutoId | データのリストに追加します。childByAutoId を呼び出すたびに、user-posts/user-id/unique-post-idのような一意の識別子としても使用できる一意のキーが生成されます。 |
updateChildValues | データのすべてを置換することなく、定義済みのパスのキーの一部を更新します。 |
runTransactionBlock | 同時更新によって破損する可能性がある複合データを更新します。 |
iOS でのデータの保存より |
#データの表示の方法
Java および Node.js では、コールバック関数は DataSnapshot を受け取ります。これはデータのスナップショットです。スナップショットとは、ある時点における特定のデータベース参照にあるデータの全体像を写し取ったものです。スナップショットの val() / getValue() を呼び出すと、データの言語固有のオブジェクト表現が返されます。参照先の場所にデータが存在しない場合、スナップショットの値が null になります。
//Fetchしたデータを入れておく配列、この配列をTableViewで表示
var contentArray: [DataSnapshot] = []
//FetchしたSnapshotsを格納する変数
var snap: DataSnapshot!
//Firebaseのルートを宣言しておく
let ref = Database.database().reference()
#xibファイルを使わずに表示する方法
参考にした記事ではxibファイルなどを使ってセル内にcontentを表示してましたが、自分はまだxibファイルの使い方側からなっか他ため、以下のように少し変更して実装しました。
class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var table: UITableView! //送信したデータを表示するTableView
var contentArray: [DataSnapshot] = [] //Fetchしたデータを入れておく配列、この配列をTableViewで表示
var snap: DataSnapshot! //FetchしたSnapshotsを格納する変数
let ref = Database.database().reference() //Firebaseのルートを宣言しておく
override func viewDidLoad() {
super.viewDidLoad()
//データを読み込むためのメソッド
self.read()
table.delegate = self //デリゲートをセット
table.dataSource = self //デリゲートをセット
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Cellの高さを調節
table.estimatedRowHeight = 56
table.rowHeight = UITableView.automaticDimension
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
//画面が消えたときに、Firebaseのデータ読み取りのObserverを削除しておく
ref.removeAllObservers()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//ViewControllerへの遷移
func transition() {
self.performSegue(withIdentifier: "toView", sender: self)
}
//セルの数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contentArray.count
}
//返すセルを決める
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell (
withIdentifier: "Cell",
for: indexPath as IndexPath)
//contetnArrayにitemを代入
let item = contentArray[indexPath.row]
//cell内に代入するものをfirebaseから持ってくる
let textlabel = item.value as! Dictionary<String, AnyObject>
//cell内に代入するものを決める
cell.textLabel?.text = String(describing: textlabel["content"]!)
return cell
}
func read() {
//FIRDataEventTypeを.Valueにすることにより、なにかしらの変化があった時に、実行
//今回は、childでユーザーIDを指定することで、ユーザーが投稿したデータの一つ上のchildまで指定することになる
ref.child((Auth.auth().currentUser?.uid)!).observe(.value, with: {(snapShots) in
if snapShots.children.allObjects is [DataSnapshot] {
print("snapShots.children...\(snapShots.childrenCount)") //いくつのデータがあるかプリント
print("snapShot...\(snapShots)") //読み込んだデータをプリント
self.snap = snapShots
}
self.reload(snap: self.snap)
})
}
//読み込んだデータは最初すべてのデータが一つにまとまっているので、それらを分割して、配列に入れる
func reload(snap: DataSnapshot) {
if snap.exists() {
print(snap)
//FIRDataSnapshotが存在するか確認
contentArray.removeAll()
//1つになっているFIRDataSnapshotを分割し、配列に入れる
for item in snap.children {
contentArray.append(item as! DataSnapshot)
}
// ローカルのデータベースを更新
ref.child((Auth.auth().currentUser?.uid)!).keepSynced(true)
//テーブルビューをリロード
table.reloadData()
}
}
}
【Firebase+swift】
— なかむら (@nakamurasssey) November 23, 2019
ユーザーと投稿コンテンツを紐付けてTableViewに表示できるようになたーーー!
これで作りたかったアプリが作れそう! pic.twitter.com/LFaP6A1hO8