Search code examples
swiftfirebasegoogle-cloud-firestorecodable

FirestoreSwift DocumentReference codable


I have the following model:

struct Organization: Codable, Identifiable {
  @DocumentID var id: String? <- Identifiable 
  let ref: DocumentReference <- Reference to the document
  let name: String
  

  enum CodingKeys: String, CodingKey {
    case name = "Name"
  }
}

I need to use the documentRef in my model for references between different databases and different sub collections.

How can I map the ref and make it codable as it isn't a field.

Furthermore do I get the error Unknown attribute 'DocumentID'

Using Firebase SDK: 10.20.0


Solution

  • It goes a little different

    struct Organization: Codable, Identifiable {
      @DocumentID var ref: DocumentReference? //This will be auto-populated when you fetch/Decode.
      var id: String? {
          ref?. documentID
      }
      let name: String
      
    
      enum CodingKeys: String, CodingKey {
    
        case name = "Name"
        case ref
    
      }
    }
    

    In theory you cannot get rid of the ? since DocumentID says Value should be Value? but you can "pre-populate" the field to minimize the chances that it could be nil.

    struct Organization: Codable, Identifiable {
        @DocumentID var ref: DocumentReference? 
        var id: String? {
            ref?.documentID
        }
        let name: String
        
        init(name: String) throws {
            self.name = name
            ref = try Firestore.firestore().collection("Organizations").addDocument(from: self)
        }
        
        enum CodingKeys: String, CodingKey {
            case name = "Name"
            case ref
        }
    }
    

    One; what I consider a very dangerous; workaround would be to use !. This would eliminate the optional but I don't know if Firebase guarantees that it will never be nil on their end. This could introduce a serious bug.

    struct Organization: Codable, Identifiable {
        @DocumentID var ref: DocumentReference!
        var id: String {
            ref.documentID
        }
        let name: String
        
        init(name: String) throws {
            self.name = name
            ref = try Firestore.firestore().collection("Organizations").addDocument(from: self)
        }
        
        enum CodingKeys: String, CodingKey {
            case name = "Name"
            case ref
        }
    }