How to map a Firestore DocumentID to a RealmObject attribute?

Viewed 250

I'm trying to provide some data in the cloud with Firestore that can be downloaded and stored in a Realm database on an iOS device. The structure of my object that I want to store is:

import Foundation
import RealmSwift
import FirebaseFirestore
import FirebaseFirestoreSwift

@objcMembers class Flashcard: Object, Codable{

@objc dynamic var id: String? = NSUUID().uuidString 
@objc dynamic var character: String?
@objc dynamic var title: String?
@objc dynamic var translation: String?
@objc dynamic var created: Date = Date()
let deck = LinkingObjects<FlashcardDeck>(fromType: FlashcardDeck.self, property: "cards")

override class func primaryKey() -> String? {
    return "id"
}

private enum CodingKeys: String, CodingKey {
    case id
    case character
    case translation
    case created
    case title
}

If I try to map the documentID to my id attribute with

@DocumentID @objc dynamic var id: String? = NSUUID().uuidString 

If get the following error:

'Primary key property 'id' does not exist on object 'Flashcard'

How can I solve this problem?

EDIT: To make it more understandable here is a screenshot of my Firestore database:

enter image description here

The collection "PredifinedDecks" will store many decks. For example the id = DF59B1B3-BD22-47CE-81A6-04E7A274B98F represents one deck. Each deck will store an array/List with cards in it.

1 Answers

Not sure I fully understand the question but let me address this at a high level.

It appears there is a PredefinedDecks (a collection) that contains documents. Each document has a field (an array) of cards and some other field data. If the goal is to read in all of the documents (the decks) and their child data and store them as Realm objects, here's one solution. Start with a Realm object to hold the data from Firestore

class DeckClass: Object {
    @objc dynamic var deck_id = ""
    @objc dynamic var created = ""
    @objc dynamic var title = ""
    let cardList = List<CardClass>()

    convenience init(withDoc: QueryDocumentSnapshot) {
        self.init()
        self.deck_id = withDoc.documentID
        self.title = withDoc.get("title") as? String ?? "no title"
        self.created = withDoc.get("created") as? String ?? "no date"
        let cardArray = withDoc.get("cards") as? [String]
        for card in cardArray {
            let card = CardClass(withCard: card) {
                self.cardList.append(card)
            }
        }
    }
}

With this, you simply pass the documentSnapshot from Firestore for each document and the class will populate its properties accordingly.

and the code to read Firestore

func readDecks() {
    let decksCollection = self.db.collection("PredefinedDecks")
    decksCollection.getDocuments(completion: { documentSnapshot, error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        for doc in documentSnapshot!.documents {
            let deck = DeckClass(withDoc: doc)
            self.decksList.append(deck) //a Realm List class object? Something else?
        }
    })
}
Related