简体   繁体   English

更新数据时 Swift Firebase 'FIRInvalidArgumentException'

[英]Swift Firebase 'FIRInvalidArgumentException' when updating data

In short, I am using image picker to upload images to firebase storage and saving the image id to a document in firestore.简而言之,我正在使用图像选择器将图像上传到 firebase 存储并将图像 ID 保存到 firestore 中的文档中。 The images are uploaded successfully however, when trying to save the data to the document I am getting an error: 'FIRInvalidArgumentException', reason: 'Unsupported type: __SwiftValue'图片已成功上传,但在尝试将数据保存到文档时出现错误:'FIRInvalidArgumentException',原因:'Unsupported type: __SwiftValue'

Why is this happening?为什么会这样?

Call to upload images, and then save to document:调用上传图片,然后保存到文档:

ImagePickerView(currentEventID: self.liveEventID, configuration: self.pickerConfig) { imagesData in
   print("PICKER DONE: \(imagesData)")
   var eventImages: [EventImage] = []
   for imageData in imagesData {
      let imageUUID = UUID().uuidString
      self.isvm.uploadImage(currentEventID: self.liveEventID, imageUUID: imageUUID, selectedImagesData: imageData) { imageURL in
                        eventImages.append(EventImage(id: imageUUID, url: imageURL, voteCount: 1))
                        
         if eventImages.count == imagesData.count {
            print("LOOP DONE: \(eventImages)")
               self.isvm.saveImagesToEvent(currentEventID: self.liveEventID, eventImages: eventImages) { isSavedToEvent in
                  if isSavedToEvent {
                     print("SAVED IMAGES SUCCESSFULLY")
                     self.isReloadingImages = true
                                    self.isvm.getUpdatedEventPhotos(currentEventID: self.liveEventID) { liveEvent in
                     self.liveEvent = liveEvent
                     if !self.liveEvent.isEmpty {
                        self.liveEventID = self.liveEvent[0].id
                        self.isReloadingImages = false
                    }
                 }
               }
            }
         }
      }
   }
}

Where the error occurs:错误发生的地方:

    public func saveImagesToEvent(currentEventID: String, eventImages: [EventImage], completion: @escaping (_ isSavedToEvent: Bool) -> Void) {
        self.eventsDataCollection.document(currentEventID).updateData([
            "eventImages" : FieldValue.arrayUnion(eventImages)
        ]) { error in
            if let error = error {
                print("ERROR SAVING URLS TO EVENT: \(error)")
                completion(false)
            }
        }
        completion(true)
    }

The data model:数据model:

struct EventModel: Identifiable, Codable {
    var id: String
    var isLive: Bool
    var coors: [Coor]
    var eventCenterCoorFormatted: [Double]
    var hostTitle: String
    var eventName: String
    var eventDescription: String
    var isEventPrivate: Bool
    var eventGuestsJoined: [String]
    var eventEndDate: String
    var eventImages: [EventImage]
    
    private enum CodingKeys: String, CodingKey {
        case id
        case isLive
        case coors
        case eventCenterCoorFormatted
        case hostTitle
        case eventName
        case eventDescription
        case isEventPrivate
        case eventGuestsJoined
        case eventEndDate
        case eventImages
    }
}

struct Coor: Identifiable, Codable {
    var id = UUID()
    var coorDoubles: [Double]
    
    private enum CodingKeys: String, CodingKey {
        case coorDoubles
    }
}

struct EventImage: Identifiable, Codable {
    var id = UUID().uuidString
    var url: String
    var voteCount: Int
    
    private enum eventImage: String, CodingKey {
        case id
        case imageURL
        case voteCount
    }
}

Please note: The last print statement before the error is: "Loop done: " And it successfully gets all the eventImages of type EventImage.请注意:错误前的最后一个打印语句是:“Loop done:”并且它成功获取了所有 EventImage 类型的 eventImage。

The error is caused by trying to save a custom Swift object to Firestore in your saveImagesToEvent function:该错误是由于尝试在您的saveImagesToEvent function 中将自定义 Swift object 保存到 Firestore 引起的:

"eventImages": FieldValue.arrayUnion(eventImages)

You need to encode your EventImage objects before trying to store them in Firestore.您需要先对EventImage对象进行编码,然后再尝试将它们存储在 Firestore 中。 Your EventImage struct already conforms to Codable , but the set/update data methods for Firestore don't automatically encode your data.您的EventImage结构已经符合Codable ,但 Firestore 的设置/更新数据方法不会自动对您的数据进行编码。

To solve this, make sure you have included the Firestore swift extensions in your project:要解决此问题,请确保您已在项目中包含 Firestore swift 扩展:

pod 'FirebaseFirestoreSwift'

Now you can use Firestore.Encoder to encode your data before sending it to Firestore:现在您可以使用Firestore.Encoder在将数据发送到 Firestore 之前对其进行编码:

val encodedEventImages = eventImages.map { Firestore.Encoder().encode($0) }

self.eventsDataCollection.document(currentEventID).updateData([
            "eventImages" : FieldValue.arrayUnion(encodedEventImages)
        ]) { error in
...

If you want to read the data in Firestore document as a custom Swift object you will need to decode it as in this example from the Firestore documentation :如果您想以自定义 Swift object 的形式读取 Firestore 文档中的数据,您需要按照 Firestore 文档中的示例对其进行解码:

docRef.getDocument { (document, error) in
    // Construct a Result type to encapsulate deserialization errors or
    // successful deserialization. Note that if there is no error thrown
    // the value may still be `nil`, indicating a successful deserialization
    // of a value that does not exist.
    //
    // There are thus three cases to handle, which Swift lets us describe
    // nicely with built-in Result types:
    //
    //      Result
    //        /\
    //   Error  Optional<City>
    //               /\
    //            Nil  City
    let result = Result {
      try document?.data(as: City.self)
    }
    switch result {
    case .success(let city):
        if let city = city {
            // A `City` value was successfully initialized from the DocumentSnapshot.
            print("City: \(city)")
        } else {
            // A nil value was successfully initialized from the DocumentSnapshot,
            // or the DocumentSnapshot was nil.
            print("Document does not exist")
        }
    case .failure(let error):
        // A `City` value could not be initialized from the DocumentSnapshot.
        print("Error decoding city: \(error)")
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM