Reputation: 3527
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.
Upvotes: 4
Views: 1247
Reputation: 932
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
}
Upvotes: 5
Reputation: 4660
Usually, this error is related to the fact that Firestore is not able to serialise different types of variables and arrays at the same time - in your case the problem seems related to the currentDevice
variable, that Firestore is not being able to identify.
It seems that you will need to modify the below part, for your application to be able to insert the data.
...
enum CodingKeys: String, CodingKey {
case manufacturer
case model
case osVersion
}
...
Since you are not using one "variable" to add the information for the manufacturer
, model
and osVersion
. I would recommend you to check this question from the Community here, to get a possible solution - adapting to your case - of how to convert your data for Firestore to be able to understand.
Let me know if the information helped you!
Upvotes: 0