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

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

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

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

Swift

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

Q&A

解決済

1回答

1647閲覧

TODOアプリの編集、削除が正しく作動しない(Swift4、Firestore)

YuukiIbata

総合スコア15

Firebase

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

Swift

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

0グッド

0クリップ

投稿2018/11/07 05:15

編集2018/11/09 02:29

前提・実現したいこと

環境はXcode10.0.0 Swift4.0です。
Todoアプリを作っています。データベースとしてはFirestoreを用いております。
削除、修正が正しく作動しないので、どこが間違っているかをお教えいただきたいです。

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

UserDefaultで保存していた時は、配列内のタスクを全部まとめて上書きしておりました。
イメージ的には、タスクが全部書かれたファイルを上書き保存する感じです。
Firestoreで取り組んでいる今回は配列に入ったタスクを1件ずつFirestoreに保存しています。
上書き時はIDを使って上書きしていますが、コードをよく読むと読み出しているときにIDをタスクに保持するようになっていません。この解消方法をご教授いただきたいです。

修正、削除前です
修正、削除前

削除後も消えておりません
削除後も消えておりません

修正しようとすると…
修正画面

なぜか増えます
修正するとなぜか増えます

該当のソースコード

FirestoreTaskRepository.swift

Swift4.0

1import Foundation 2import FirebaseFirestore 3 4class FirestoreTaskRepository: TaskRepositoryProtocol { 5 6 let db = Firestore.firestore() 7 8 init(){ 9 let settings = db.settings 10 settings.areTimestampsInSnapshotsEnabled = true 11 db.settings = settings 12 } 13 14 // ユーザー毎のデータベースへの参照を取得する 15 private func getCollectionRef () -> CollectionReference { 16 guard let uid = User.shared.getUid() else { 17 fatalError ("Uidを取得出来ませんでした。") 18 } 19 return db.collection("users").document(uid).collection("tasks") 20 } 21 22 func save(_ tasks: [Task], completion: (() -> Void)) { 23 // TODO トランザクション 24 let collectionRef = getCollectionRef() 25 tasks.forEach { (task) in 26 if let id = task.id { 27 let documentRef = collectionRef.document(id) 28 documentRef.setData(task.toData()) 29 } else { 30 31 let documentRef = collectionRef.addDocument(data: task.toData()) 32 task.id = documentRef.documentID 33 } 34 } 35 36 // firestoreへの保存は非同期ではない(後でバックグラウンドで同期をしている?) 37 completion() 38 } 39 40 func load(completion: @escaping (([Task]) -> Void)) { 41 print ("データロード") 42 var tasks: [Task] = []; 43 let collectionRef = getCollectionRef() 44 collectionRef.getDocuments { (querySnapshot, error) in 45 if let error = error { 46 print (error.localizedDescription) 47 }else if let documents = querySnapshot?.documents { 48 documents.forEach({ (document) in 49 if document.exists { 50 let data = document.data() 51 let task = Task(data: data) 52 tasks.append(task) 53 } 54 }) 55 } 56 completion(tasks) 57 } 58 59 } 60} 61 62

Task.swift

Swift4.0

1 2import UIKit 3 4class Task: Codable { 5 var id: String? 6 var title: String? 7 var note: String? 8 var latitude: Double? 9 var longitude: Double? 10 11 enum CodingKeys: String, CodingKey { 12 case title 13 case note 14 case latitude 15 case longitude 16 } 17 18 init(title _title: String) { 19 self.title = _title 20 } 21 22 init(data: [String: Any]) { 23 if let title = data["title"] as? String { 24 self.title = title 25 } 26 if let note = data["note"] as? String { 27 self.note = note 28 } 29 if let latitude = data["latitude"] as? Double { 30 self.latitude = latitude 31 } 32 if let longitude = data["longitude"] as? Double { 33 self.longitude = longitude 34 } 35 } 36 37 required init(from decoder: Decoder) throws { 38 let container = try decoder.container(keyedBy: CodingKeys.self) 39 self.title = try container.decode(String.self, forKey: .title) 40 self.note = try container.decode(String.self, forKey: .note) 41 self.latitude = try container.decode(Double.self, forKey: .latitude) 42 self.longitude = try container.decode(Double.self, forKey: .longitude) 43 } 44 func encode(to encoder: Encoder) throws { 45 var container = encoder.container(keyedBy: CodingKeys.self) 46 try container.encode(title, forKey: .title) 47 try container.encode(note, forKey: .note) 48 try container.encode(latitude, forKey: .latitude) 49 try container.encode(longitude, forKey: .longitude) 50 } 51 52 func toData() -> [String: Any] { 53 return [ 54 "title": self.title!, 55 "note": self.note!, 56 "latitude": self.latitude!, 57 "longitude": self.longitude! 58 ] 59 } 60 61} 62 63

試したこと

他のファイル情報が必要でしたらお教えいただけると幸いです。

”Firestoreで取り組んでいる今回は配列に入ったタスクを1件ずつFirestoreに保存しています。
上書き時はIDを使って上書きしていますが、コードをよく読むと読み出しているときにIDをタスクに保持するようになっていません。”
というのは頂いたヒントなのですが、どのように修正したら良いかが分かっておりません…。ロード部分に問題があるのかと思うのですが…。

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

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

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

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

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

kakajika

2018/11/09 01:50 編集

大体状況はわかりましたが、念のためTaskクラスの中身も載せてください。
guest

回答1

0

ベストアンサー

読み込み部分で以下のようにtaskにidを設定する処理を追加すれば、データの更新ができるようになると思います。

swift

1documents.forEach({ (document) in 2 if document.exists { 3 let data = document.data() 4 let task = Task(data: data) 5 task.id = document.documentID // taskにidを設定 6 tasks.append(task) 7 } 8})

投稿2018/11/09 03:19

編集2018/11/09 05:51
kakajika

総合スコア3131

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

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

YuukiIbata

2018/11/09 04:51 編集

ありがとうございます…!! 目の付け所は間違っていなかったようなのですが、どうしたら良いかわかっていなかったので本当に助かります…! Value of type 'QueryDocumentSnapshot' has no member 'id' というエラーが出てしまったのですが、どのように突破したら良いでしょうか??答えが聞けると一番ありがたいのですが、ヒントだけでもお教えていただければ幸いです…!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問