firebase-ios-sdk: Crash when trying to `updateData`/`setData` for individual fields.
[REQUIRED] Step 1: Describe your environment
- Xcode version: 13.2.1 (13C100)
- Firebase SDK version: 8.14.0
- Installation method:
Swift Package Manager - Firebase Component: Firestore
- Target platform(s):
iOS
[REQUIRED] Step 2: Describe the problem
Steps to reproduce:
The IOS Application crashes when trying im trying to use asynchronously (didn’t tested it synchronously) one of the following:
-
... .updateData([ "deviceModels": FieldValue.arrayRemove(oldDeviceModels) }) -
... .updateData([ "deviceModels": FieldValue.arrayUnion(newDeviceModels) }) -
... .updateData([ "deviceModels": newDeviceModels }) -
... .setData([ "deviceModels": newDeviceModels })
The only error im getting is Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT). But when going trough the stack trace I can see that it was caused by the function .updateData([]).
However FieldValue.delete() works just fine, as well as overwriting the hole document instead of just the field (via .setData(from: categoryModel).
I hope this is not an issue on my side, but if so im sorry to bother you. If you need more information don’t hesitate to ask. Thank you for your time!
Relevant Code:
Models
import Foundation
import FirebaseFirestoreSwift
struct CategoryModel: Identifiable, Codable {
@DocumentID var id: String?
let name: String
var deviceModels: [DeviceModel]
}
struct DeviceModel: Identifiable, Codable {
let id: String
let name: String
let imageURL: URL
let model: String
let brand: String
let purchaseDate: Date
let purchasePrice: Double
let warrantyPeriod: Date
let imageAssets: [URL]
let pdfAssets: [URL]
let repairModels: [RepairModel]
}
struct RepairModel: Identifiable, Codable {
let id: String
let name: String
let repairDate: Date
let repairPrice: Double
let warrantyPeriod: Date
}
FirestoreViewModel
public func arrayRemove(document: String, field: String, array: [DeviceModel]) async {
//self.actionState = .isLoading(action: .arrayRemove) - Not Important
do {
try await self.db.collection(self.collection).document(document).updateData([
field: FieldValue.arrayRemove(array)
])
//self.actionState = .none - Not Important
} catch {
//self.actionState = .error(error: error) - Not Important
}
}
View (SwiftUI)
internal let categoryModel: CategoryModel
@EnvironmentObject private var firestoreViewModel: FirestoreViewModel
// - Some view
.onDelete { offsets in
let deviceModelsToDelete = offsets.map { self.categoryModel.deviceModels[$0] }
Task.detached {
await self.firestoreViewModel.arrayRemove(document: self.categoryModel.id!, field: "deviceModels", array: deviceModelsToDelete)
}
}
About this issue
- Original URL
- State: open
- Created 2 years ago
- Comments: 21 (11 by maintainers)
@wu-hui I tested it and your workaround indeed works perfectly. Here is the valid swift code in case someone else is having the same issue:
I hope this issue gets fixed soon, and please ask if you need further information, or something else from me 😃
Thanks Morgan, this is probably less a bug more a limitation, see below.
@lucaszischka The problem here is that Firestore’s Codable implementation does not support directly using codables as fields. They are only meant to be used as documents.
If you intend to use them as fields, they need to be wrapped around another codable, and this only works with
setData.To set an individual field using a codable however, you need to explicitly convert the codable to a
Dictionarylike thistry Firestore.Encoder().encode(codeableInstance), then pass the returned dictionary toarrayRemoveand similar.OTOH, we will do below from our side:
You are right, I lost the context and closed it.