Open cerupcat opened 6 years ago
Struggling with this as well as Firestore has now made the push to FIRTimestamp
and .dateValue
. Would be happy to do a PR for the feature if I could get a little guidance.
@cerupcat I would not use this in production, but here's a hack I was able to get FIRTimestamps working with. Again... it's a HACK, be forewarned.
Thanks, i'll take a look.
Hey guys! First of all, sorry for being unresponsive lately... I am really glad that there is support from community!
About the issue. I think that the proper way to do it, would be to do something similar to here. So we can make FirTimestamp Encodable and it will be skipped and left untouched when encoding and thus will let the Firestore handle it. I will open a PR with an example of how to use it! What do you think about it?
@alickbass would be great if we get some best practice guidance on that!
Hey guys! The PR makes Timestamp conform to Codable
and you can use it directly in your code just like normal Date
. Something like below:
import CodableFirebase
extension Timestamp: TimestampType {}
struct FirTimestampModel: Codable {
let timestamp: Timestamp
}
let timestamp = FirTimestampModel(timestamp: Timestamp(date: Date()))
let data = try! FirestoreEncoder().encode(timestamp)
If you want to use Date in your models and convert to Timestamp on server, I would really discourage that, as then you will lose all the precision.
Thank you for your effort 👍
Thanks @alickbass! Agree to disagree about having Timestamp in your models though. Creating a dependency on Firestore for the Timestamp type at the model layer doesn't feel good to me.
Well, I think that the reason to use FirTimestamp
in the first place is that you are not satisfied with the precision of the Date
. Why not use Date
directly then?
Yeah, I would prefer to use Date
directly but a recent version of Firestore told (via a console message) that the using of Date
was going to be deprecated and the correct thing to do was get dateValue
of FIRTimestamp
. That's actually the thing that got me involved in this issue, precision wasn't so much of a concern.
The behavior for system Date objects stored in Firestore is going to change AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to add the following code to your app before calling any other Cloud Firestore methods:
let db = Firestore.firestore()
let settings = db.settings
settings.areTimestampsInSnapshotsEnabled = true
db.settings = settings
With this change, timestamps stored in Cloud Firestore will be read back as Firebase Timestamp objects instead of as system Date objects. So you will also need to update code expecting a Date to instead expect a Timestamp. For example:
// old:
let date: Date = documentSnapshot.get("created_at") as! Date
// new:
let timestamp: Timestamp = documentSnapshot.get("created_at") as! Timestamp
let date: Date = timestamp.dateValue()
Please audit all existing usages of Date when you enable the new behavior. In a future release, the behavior will be changed to the new behavior, so if you do not follow these steps, YOUR APP MAY BREAK.
Valid point, @dannypier... Maybe I will find a better alternative... I will keep you updated, guys
@alickbass Right now Firestore is crashing while using Date objects in the model, and I am also not very keen to be using FIRTimestamp in my model objects. It's not a dependency I'd like to have in my project as we might shift from Firestore in the future.
Edit: Firestore wasn't crashing because of the FIRTimestamp. Sorry, had a wrong call because of another Google product.
I took an attempt at supporting this. I realized the best way to do it is while encoding a Date
object to convert it into FIRTimestamp
with their initializer + (instancetype)timestampWithDate:(NSDate *)date;
and while decoding if expecting a Date
object taking the FIRTimestamp
and doing timestamp.dateValue()
and if expecting it as FIRTimestamp
just return that
However, to achieve this CodableFirebase
has to have access to FIRTimestamp in the project, that would mean we would need to add the Firestore pod into the project. I'm not sure how open you are to doing this.
In general, I am okay with adding Firebase as a dependency and removing all the redundant protocols and just working with Firebase / Firestore values. If you guys are willing to contribute, please submit a PR and I would love to review. Unfortunately, I haven't had time lately to submit any code myself
@alickbass I'll work on it this weekend. I was busy this past week. I'm going to try to do it without actually including Firebase as a dependency, if I am not able I'll just go ahead and add it.
@serjooo tbh, I would like to add it as a dependency and remove all the weird protocols that we have.
@alickbass What method do you see best fitting to add Firebase as a dependency? I stumbled upon this issue where things become a little tricky to add Firebase through Cocoapods
Was this ever solved? @serjooo @alickbass
@jimijon not yet. We need to add Firebase as a dependency of this project; however, I really had some hard time doing it and never had the time to research and give a shot again, but most probably I'll try to contribute again as I'm thinking of using CodableFirebase again for a future project of mine.
@serjooo @alickbass any updates on this and/or is there any workaround? I had to update Firestore so I can use their new collection group query but keep running into the crash when decoding Date in the new version (Firebase 6.0.0, Firestore 1.3.0).
@alickbass I finally found sometime to work on this today and I included the FirebaseFirestore
pod as a dependency to CodableFirebase
and started working on the Encoding
and Decoding
. However, I realized Google are almost ready to merge in your implementation and some changes on to master via this PR https://github.com/firebase/firebase-ios-sdk/pull/2229
Do you think its still worth investing more time and doing the same implementation as that PR on CodableFirebase
and merge it until they release?
Also something to note adding FirebaseFirestore
stops support for macOS
watchOS
and tvOS
because the Podspec lint errored as FirebaseFirestore
itself doesn't have official support for them
I have started working on that PR myself quite some time ago, however, due to change in work could not continue... I am not sure what is their roadmap and timeline is...
Yes you are right it seems like they keep postponing the release and you can never be sure of what their timeline is. How about you submit a PR of your current work on a separate branch and we can work on it together?
sorry, I meant the PR on Firebase itself 😂I haven't done anything here yet, so feel free to submit your ideas 😎
let date: Date = timestamp.dateValue()
perfect one . it's woking for me. thank you so much for sharing
So, what happened with this ? I'm still dealing with
Expected to decode Date but found FIRTimestamp instead.
What do you guys suggest to solve this ? I have a Date object in my model
So, what happened with this ? I'm still dealing with
Expected to decode Date but found FIRTimestamp instead.
What do you guys suggest to solve this ? I have a Date object in my model } **
let timestamp: Timestamp = dicDocument["Date"] as! Timestamp let timeStmp = timestamp.dateValue() msg.date = timeStmp
** i have taken date variable and its type is Date() in model. i have stored date as timeStamp in firestore.
@alickbass seems like Google merged Codable support into master https://github.com/firebase/firebase-ios-sdk/pull/3198 didn't check the implementation or test it out myself. Will do that and close this issue accordingly
So, what happened with this ? I'm still dealing with Expected to decode Date but found FIRTimestamp instead. What do you guys suggest to solve this ? I have a Date object in my model } **
let timestamp: Timestamp = dicDocument["Date"] as! Timestamp let timeStmp = timestamp.dateValue() msg.date = timeStmp
** i have taken date variable and its type is Date() in model. i have stored date as timeStamp in firestore.
How did you end up doing this?
@alickbass seems like Google merged Codable support into master firebase/firebase-ios-sdk#3198 didn't check the implementation or test it out myself. Will do that and close this issue accordingly
How does it compare to this library?
I'm running into this On my model I have these values:
var created: Date?
var updated: Date?
Firestore is returning them in this format: "updated": <FIRTimestamp: seconds=1617128658 nanoseconds=859000000>
My understanding is that I could use this library to decode from Timestamp directly to date like this:
let model = try FirestoreDecoder().decode(Model.self, from: item.data())
Unfortunately it throws the error: typeMismatch(Foundation.Date, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "created", intValue: nil)], debugDescription: "Expected to decode Date but found FIRTimestamp instead.", underlyingError: nil))
Does anyone know how to solve this? I'm pulling my hair out trying to avoid writing a custom initializer or even a custom model for the one area of the app where this model gets loaded up from the Firestore.
I'm trying to figure out how map to FIRTimestamp since it's not codable currently. Is there a way to transform the data returned from FIRTimestamp to Date instead or make FIRTimestamp codable so that it maps correctly?