Skip to content

Conversation

@andrewheard
Copy link
Contributor

Updated the DocumentID Swift property wrapper's value property to be private(set) since it is ignored in the methods that write to Firestore.

Existing Implementation (See issue #9368)

struct User: Codable {
  @DocumentID var id: String?
  var name: String
}

var user = User(name: "Foo")
user.id = "abc123"  // This line is ignored

try! Firestore.firestore().collection("users").document("def456").setData(from: user)
// User is written to "users/def456", `user.id` is ignored.

Updated Implementation

// Compiler Error: Cannot assign to property: 'id' is a get-only property
user.id = "abc123"  

API

  • This could be considered an API change and may need to go through review

Updated the `DocumentID` Swift property wrapper's `value` property to be private(set) since it is ignored in the methods that write to Firestore.
@paulb777
Copy link
Member

paulb777 commented Sep 2, 2022

Also may considered a breaking change. Adding @peterfriese for input

Copy link
Contributor

@peterfriese peterfriese left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am generally in favour of this, since it makes the current behaviour explicit. To my knowledge, there is no way to ever change a Firestore document ID.

I'd like to suggest to document this behaviour at a suitable place on the property wrapper.

Also, I am not sure if it's possible to write a test for this?

@mortenbekditlevsen
Copy link
Contributor

It's true that you can't change an id, but you could expect an initial write to use a manually set document id. This, however, is not how the api works, so making it read only will clarify any confusion one might have had about that behavior.

@paulb777 paulb777 added this to the Firebase 10 - M122 milestone Sep 8, 2022
@paulb777
Copy link
Member

LGTM, adding @chliangGoogle for API review.

Made the setter internally accessible and imported FirebaseFirestoreSwift with @testable.
@andrewheard
Copy link
Contributor Author

I'd like to suggest to document this behaviour at a suitable place on the property wrapper.

Also, I am not sure if it's possible to write a test for this?

@peterfriese I've attempted to add some more documentation to the property wrapper to clarify the usage. I'm not sure that it's possible to write a test for this, beyond the existing @DocumentId usage tests, because they'd need to be non-compile tests to verify that setting isn't possible. I've only done that manually.

@andrewheard
Copy link
Contributor Author

It's true that you can't change an id, but you could expect an initial write to use a manually set document id. This, however, is not how the api works, so making it read only will clarify any confusion one might have had about that behavior.

@mortenbekditlevsen That's helpful feedback though and we'll want to keep it in mind when designing APIs in the future.

@google-oss-bot
Copy link

google-oss-bot commented Sep 21, 2022

Coverage Report 1

Affected Products

  • FirebaseFirestore-iOS-FirebaseFirestore.framework

    Overall coverage changed from 87.93% (a6164a8) to 87.91% (21efad9) by -0.02%.

    FilenameBase (a6164a8)Merge (21efad9)Diff
    leveldb_key.cc98.33%98.14%-0.20%
    leveldb_remote_document_cache.cc96.25%94.38%-1.88%
  • FirebaseFirestore-iOS-FirebaseFirestoreSwift.framework

    Overall coverage changed from 45.67% (a6164a8) to 45.50% (21efad9) by -0.17%.

    FilenameBase (a6164a8)Merge (21efad9)Diff
    DocumentID.swift87.88%80.56%-7.32%

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/svP2VPx1eF.html

# Conflicts:
#	Firestore/Swift/CHANGELOG.md
#	Firestore/Swift/Source/Codable/DocumentID.swift
@paulb777 paulb777 dismissed peterfriese’s stale review September 27, 2022 21:04

Unblock for merge today

ncooke3 and others added 3 commits September 28, 2022 01:14
#10275)

* [Firestore] Mark `@DocumentID` setter deprecated and add log statement in init

* Fix typo in import

* Update CHANGELOG

* Review and remove deprecation

* Review and add FIRLogWarningSwift

* Add FirebaseCorExtension to Firestore's Podfile
@ncooke3
Copy link
Member

ncooke3 commented Sep 28, 2022

Merged associated PRs and resolved simple conflicts in the last two commits. Proceeding with merge. Will move release tags, stage FirebaseFirestoreSwift.podspec (and Analytics specs!), and kick off zip build.

@ncooke3 ncooke3 merged commit 8866b22 into master Sep 28, 2022
@ncooke3 ncooke3 deleted the ah-firestore-documentid branch September 28, 2022 05:42
@ncooke3
Copy link
Member

ncooke3 commented Sep 28, 2022

"[FirebaseFirestoreSwift]",
"I-FST000002",
"""
Attempting to initialize or set a @DocumentID property with a non-nil
Copy link
Contributor

@peterfriese peterfriese Sep 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking the error message like this results in the following, which is less than ideal:

2022-09-28 12:49:44.813075+0200 Make It So[29167:1864911] 10.0.0 - [FirebaseFirestoreSwift][I-FST000002] Attempting to initialize or set a @DocumentID property with a non-nil
value: B89FE0DD-7ACB-4D55-9FBE-CFC70512E760. The document ID is managed by Firestore and any
initialized or set value will be ignored. The ID is automatically set
when reading from Firestore."

Can we make sure the error message ends up being a single line? It also seems like there is a stray quotation mark at the end.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @peterfriese, if you don't mind and your app still running... Could you suggest the formatted string that renders it better?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! In a comment, or rather on a follow-up PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do a follow-up PR!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I didn't reply in time. This looks good to me on the console:

message: "Attempting to initialize or set a @DocumentID property with a non-nil value:"
  + " \"\(value)\". The document ID is managed by Firestore and any initialized or set value"
  + " will be ignored. The ID is automatically set when reading from Firestore."

I'm hoping the compiler will optimize it into one long string but it may do concatenation at runtime, not sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found a way to use multi-line strings, see #10289

get { value }
set { value = newValue }
set {
if let someNewValue = newValue {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why we use someNewValue here? In line 111, we use if let value = value.

Copy link
Member

@ncooke3 ncooke3 Sep 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I recall being confused about introducing another newValue into the scope. Mainly because I didn't know if it could cause problems on L123. Swift should be able to understand that the non-optional newValue is used in the unwrapped scope and the optional newValue should be set in the outer scope on L123. But I figured it was possible that an older Swift version may not know. To be extra safe (it was getting late when I worked on this 😅 ), I opted for introducing a new name in the scope.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess in Swift 5.7, we should even be able to use

if let newValue {
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can use this feature yet since we still need to build for devs using Xcode 13.3.1 x Swift 5.6.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just verified my assumption.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, wrt the below #10167 (comment), the setter should log if you did something like:

struct Model: Codable {
  @DocumentID var id: String = "hello"
}

let model = // ...
model.id = nil  // ⚠️ Logs a warning ⚠️

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FirestoreSwift Library: Setting a @DocumentId fails all future saves

6 participants