First off, a huge thank you to @workingdog_support_Ukraine and @Paulw11 for your incredibly helpful guidance. Your suggestions were spot on and helped me solve my issue with the G flag indicator not updating its color when toggled.
Following your suggestions, I implemented several critical changes:
As @Paulw11 suggested, I changed my RSSItem
class to use the @Observable
macro. This was indeed the architectural change needed to make individual property changes reactive:
@Observable
final class RSSItem: Identifiable, Codable {
// properties...
var g: Bool?
// Added direct methods on the model to update Firestore
func updateGValue(_ newValue: Bool?) {
// Update property
self.g = newValue
// Update Firestore asynchronously
Task {
do {
try await Self.db.collection("collection").document(id).updateData(["g": newValue as Any])
print("Updated G value to \(String(describing: newValue)) for article \(id)")
} catch {
print("Failed to update G value in Firestore: \(error.localizedDescription)")
}
}
}
}
2. Added Unique IDs to G Indicators
To force SwiftUI to rebuild the indicator when the G value changes:
Text("G")
.font(.subheadline)
.foregroundColor(article.g ?? false ? .green : .red)
.id("g-indicator-\(article.id)-\(article.g ?? false)")
3. Fixed Navigation Structure
As @workingdog_support_Ukraine suggested, the navigation structure was improved to properly handle the passing of articles between views:
DetailView(
article: selectedItem,
viewModel: viewModel
)
4. Added DocumentSnapshot Support
Added an extension to handle both QueryDocumentSnapshot
and DocumentSnapshot
:
extension RSSItem {
static func from(document: DocumentSnapshot) -> RSSItem? {
// Convert DocumentSnapshot to RSSItem
}
}
Added proper thread safety by ensuring updates happen on the main thread and using Task for asynchronous Firestore operations.
The key insight was that the array-based approach wasn't working because as @Paulw11 pointed out, "@Published won't get publishing events when an Article in the array is changed." Moving to the @Observable macro with direct state management solved this fundamental issue.
I now have a much cleaner architecture where the model itself handles its Firestore updates, making the code more maintainable and the UI properly reactive.