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