My Firestore document structure, i created it via Android:
--- Document
----- testA (object)
----- testB (array)
------- 0: Device item 1
------- 1: Device item 2
I have following struct:
import Foundation
public struct Device: Codable {
    var manufacturer: String?
    var model: String?
    var osVersion: String?
    enum CodingKeys: String, CodingKey {
        case manufacturer
        case model
        case osVersion
    }
}
My device object
let currentDevice = Device(manufacturer: "a", model: "b", osVersion: "c")
Test A: Update Device to Document.
I tried below code:
db.collection("testCollection").document("testDoc").updateData([testA: currentDevice])
...
Test B: Add Device to testB array.
db.collection("testCollection").document("testDoc")
.updateData([testA: FieldValue.arrayUnion([currentDevice])])
It all cause below error: Terminating app due to uncaught exception 'FIRInvalidArgumentException', reason: 'Unsupported type: __SwiftValue'
I also checked official document but it does not show anyway to update struct object to Firestore. What can i do? Thanks.
Hopefully this helps somebody out.
First, in the original example above, testA is not quoted.  The field key is a string.  It should be "testA"
In order to save an item to an array on a document ref, using updateData, swift structs/classes need to be encoded into a dictionary.  FirebaseFirestoreSwift helps with this by providing a specialized encoder.  Otherwise, you can manually convert from your struct into the expected [String: Any] dictionary.
This example uses FirebaseFirestoreSwift
        let currentDevice = Device(
             manufacturer: "a", 
             model: "b", 
             osVersion: "c"
        )
        // declare outside of the try/catch block
        let encoded: [String: Any]
        do {
            // encode the swift struct instance into a dictionary
            // using the Firestore encoder
            encoded = try Firestore.Encoder().encode(currentDevice)
        } catch {
            // encoding error
            handleError(error)
            return
        }
        let fieldKey = "testA"
        // add a new item to the "testA" array.
        db.collection("testCollection").document("testDoc")
            .updateData(
                [
                    fieldKey: FieldValue.arrayUnion([encoded])
                ]
            ) { error in
                guard let error = error else {
                    // no error, that's great
                    return
                }
                // uh oh, firestore error
                handleError(error)
                return
            }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With