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

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

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

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

NoSQL

NoSQL(not only SQL)は、リレーショナルデータベース管理システムとは異なるデータベースシステムを指す言葉です。

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Xcode

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

Swift

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

Q&A

解決済

1回答

2930閲覧

【Swift】Cloud Firestore addSnapshotListener{}とupdateData()を使って変数をうまくデータベースに登録できない

kizahashi

総合スコア17

Firebase

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

NoSQL

NoSQL(not only SQL)は、リレーショナルデータベース管理システムとは異なるデータベースシステムを指す言葉です。

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/09/01 18:55

前提・実現したいこと

お世話になっております。

SwiftとCloud Firestoreを使用してチャットアプリを作成しています。
Firebaseを使うのは初心者なので初歩的な質問になりますよろしくお願いします。

チャットアプリにはユーザーが名前を決めて作成できるルームがあり、いいねボタンを押すとそのルーム自体の「いいね数」が増えるような実装にしたいと思っております。

いいね数は押された分だけ増えるようにしたいです。できればもう一度ボタンを押すといいねを取り消せることも可能にしたいと思っております。

発生している問題・エラーメッセージ

イメージ説明
document"room49"に入っているデータ["iineCount":5]の5の部分にグローバル変数であるiineCount2を代入しようと思っています。

ボタンを押すとaddSnapshotListener{}が呼ばれていいね数を取得。それに1プラスしてupdateData()でデータベースを更新するというやり方でやっています。

以下のソースコードではいいね数は加算されるのですが、1回目に押した時だけは加算されず0のままです。
またアプリを起動し直していいね!ボタンを押すとまた0からになってしまいます。
おそらくiineCount2の初期値である0に戻っていると思われます。

該当のソースコード

Swift

1import UIKit 2import FirebaseFirestore 3 4var iineCount2 = 0

Swift

1@IBAction func iineBAction(_ sender: Any) { 2 let db = Firestore.firestore() 3 let ref = db.collection("rooms").document("commentRoom").collection("commentRoom2").document("room47") 4 5 ref.addSnapshotListener{ (documentSnapshot, error) in 6 guard let documentSnapshot = documentSnapshot 7 else{ 8 print("Error fetching document: (error!)") 9 return 10 } 11 let source = documentSnapshot.metadata.hasPendingWrites ? "Local" : "Server" 12 print("(source) data : (String(describing: documentSnapshot.data()))") 13 14 let toridashi = documentSnapshot.data()?["iineCount"]!//ここでいいねカウントだけ取り出す 15 iineCount2 = toridashi! as! Int 16 iineCount2 += 1 17 } 18 19 ref.updateData(["iineCount":iineCount2]){ err in 20 21 if let err = err { 22 print("Error writing document: (err)") 23 } else { 24 print("Document successfully written!") 25 }} 26 27 } 28

試したこと

  • iineCount2を定義する場所をIBAction内の一番上に変えた

毎回0に初期化されるのでいいね数は1にしかならない
.
.

  • iineCount2を定義する場所をIBAction内のaddSnapshotListener{}とupdateData()の間に変えた

よくわからないがupdateData()方が先に実行され上と同じ結果
.
.

  • iineCount2を定義する場所をaddSnapshot{}内に変えた

updateData()にiineCount2を置けない
.
.

  • addSnapshot{}内にupdateData()を入れてみた

理由はわからないがものすごい勢いで加算されていく

補足情報(FW/ツールのバージョンなど)

Swift5
Firestore 1.4.5

そもそもこのようなやり方ではないやり方があるのでしたら教えていただけたら幸いです。

ご回答よろしくお願いいたします!

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

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

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

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

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

guest

回答1

0

ベストアンサー

https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja

にしたがって、 viewDidLoad() などで Cloud Firestore からデータを取得 -> view にセットする必要があるかと思います。

class ViewController { let db = Firestore.firestore() let ref = db.collection("rooms").document("commentRoom").collection("commentRoom2").document("room47") var iineCount2 = 0 override func viewDidLoad() { super.viewDidLoad() iineCount2 = // ????のFirestoreのデータ取得に従って初期化 // addSnapshotListener はつまり、lambda(????の中身の部分) を登録することなので、ボタンを押すたび lambda を登録してしまうと、 lambda が登録回数分実行されてしまう // ので、 viewDidLoad 等の初期化時に一回行うだけで良い ref.addSnapshotListener{ (documentSnapshot, error) in guard let documentSnapshot = documentSnapshot else{ print("Error fetching document: (error!)") return } let source = documentSnapshot.metadata.hasPendingWrites ? "Local" : "Server" print("(source) data : (String(describing: documentSnapshot.data()))") let toridashi = documentSnapshot.data()?["iineCount"]!//ここでいいねカウントだけ取り出す iineCount2 = toridashi! as! Int // 取り出すだけ } } @IBAction func iineBAction(_ sender: Any) { iineCount2 += 1 ref.updateData(["iineCount":iineCount2]){ err in // 保存だけで良い if let err = err { print("Error writing document: (err)") } else { print("Document successfully written!") }} } }

投稿2019/09/01 19:00

編集2019/09/01 19:16
unhappychoice

総合スコア1531

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

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

kizahashi

2019/09/01 19:16

addSnapshotListener{}をIBAction内からViewDidLoad内に書き換えたところうまくいくようになりました。 とても素早くてシンプルな回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問