FIRQuerySnapshot.mm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <utility>
  17. #import "Firestore/Source/API/FIRQuerySnapshot+Internal.h"
  18. #import "FIRFirestore.h"
  19. #import "FIRSnapshotMetadata.h"
  20. #import "Firestore/Source/API/FIRDocumentChange+Internal.h"
  21. #import "Firestore/Source/API/FIRDocumentSnapshot+Internal.h"
  22. #import "Firestore/Source/API/FIRQuery+Internal.h"
  23. #import "Firestore/Source/Core/FSTQuery.h"
  24. #import "Firestore/Source/Model/FSTDocument.h"
  25. #import "Firestore/Source/Model/FSTDocumentSet.h"
  26. #import "Firestore/Source/Util/FSTUsageValidation.h"
  27. #include "Firestore/core/src/firebase/firestore/core/view_snapshot.h"
  28. using firebase::firestore::core::ViewSnapshot;
  29. NS_ASSUME_NONNULL_BEGIN
  30. @interface FIRQuerySnapshot ()
  31. - (instancetype)initWithFirestore:(FIRFirestore *)firestore
  32. originalQuery:(FSTQuery *)query
  33. snapshot:(ViewSnapshot &&)snapshot
  34. metadata:(FIRSnapshotMetadata *)metadata;
  35. @property(nonatomic, strong, readonly) FIRFirestore *firestore;
  36. @property(nonatomic, strong, readonly) FSTQuery *originalQuery;
  37. - (const ViewSnapshot &)snapshot;
  38. @end
  39. @implementation FIRQuerySnapshot (Internal)
  40. + (instancetype)snapshotWithFirestore:(FIRFirestore *)firestore
  41. originalQuery:(FSTQuery *)query
  42. snapshot:(ViewSnapshot)snapshot
  43. metadata:(FIRSnapshotMetadata *)metadata {
  44. return [[FIRQuerySnapshot alloc] initWithFirestore:firestore
  45. originalQuery:query
  46. snapshot:std::move(snapshot)
  47. metadata:metadata];
  48. }
  49. @end
  50. @implementation FIRQuerySnapshot {
  51. // Cached value of the documents property.
  52. NSArray<FIRQueryDocumentSnapshot *> *_documents;
  53. // Cached value of the documentChanges property.
  54. NSArray<FIRDocumentChange *> *_documentChanges;
  55. BOOL _documentChangesIncludeMetadataChanges;
  56. ViewSnapshot _snapshot;
  57. }
  58. - (instancetype)initWithFirestore:(FIRFirestore *)firestore
  59. originalQuery:(FSTQuery *)query
  60. snapshot:(ViewSnapshot &&)snapshot
  61. metadata:(FIRSnapshotMetadata *)metadata {
  62. if (self = [super init]) {
  63. _firestore = firestore;
  64. _originalQuery = query;
  65. _snapshot = std::move(snapshot);
  66. _metadata = metadata;
  67. _documentChangesIncludeMetadataChanges = NO;
  68. }
  69. return self;
  70. }
  71. - (const ViewSnapshot &)snapshot {
  72. return _snapshot;
  73. }
  74. // NSObject Methods
  75. - (BOOL)isEqual:(nullable id)other {
  76. if (other == self) return YES;
  77. if (![[other class] isEqual:[self class]]) return NO;
  78. return [self isEqualToSnapshot:other];
  79. }
  80. - (BOOL)isEqualToSnapshot:(nullable FIRQuerySnapshot *)snapshot {
  81. if (self == snapshot) return YES;
  82. if (snapshot == nil) return NO;
  83. return [self.firestore isEqual:snapshot.firestore] &&
  84. [self.originalQuery isEqual:snapshot.originalQuery] && _snapshot == snapshot.snapshot &&
  85. [self.metadata isEqual:snapshot.metadata];
  86. }
  87. - (NSUInteger)hash {
  88. NSUInteger hash = [self.firestore hash];
  89. hash = hash * 31u + [self.originalQuery hash];
  90. hash = hash * 31u + _snapshot.Hash();
  91. hash = hash * 31u + [self.metadata hash];
  92. return hash;
  93. }
  94. @dynamic empty;
  95. - (FIRQuery *)query {
  96. return [FIRQuery referenceWithQuery:self.originalQuery firestore:self.firestore];
  97. }
  98. - (BOOL)isEmpty {
  99. return _snapshot.documents().isEmpty;
  100. }
  101. // This property is exposed as an NSInteger instead of an NSUInteger since (as of Xcode 8.1)
  102. // Swift bridges NSUInteger as UInt, and we want to avoid forcing Swift users to cast their ints
  103. // where we can. See cr/146959032 for additional context.
  104. - (NSInteger)count {
  105. return _snapshot.documents().count;
  106. }
  107. - (NSArray<FIRQueryDocumentSnapshot *> *)documents {
  108. if (!_documents) {
  109. FSTDocumentSet *documentSet = _snapshot.documents();
  110. FIRFirestore *firestore = self.firestore;
  111. BOOL fromCache = self.metadata.fromCache;
  112. NSMutableArray<FIRQueryDocumentSnapshot *> *result = [NSMutableArray array];
  113. for (FSTDocument *document in documentSet.documentEnumerator) {
  114. [result addObject:[FIRQueryDocumentSnapshot
  115. snapshotWithFirestore:firestore
  116. documentKey:document.key
  117. document:document
  118. fromCache:fromCache
  119. hasPendingWrites:_snapshot.mutated_keys().contains(document.key)]];
  120. }
  121. _documents = result;
  122. }
  123. return _documents;
  124. }
  125. - (NSArray<FIRDocumentChange *> *)documentChanges {
  126. return [self documentChangesWithIncludeMetadataChanges:NO];
  127. }
  128. - (NSArray<FIRDocumentChange *> *)documentChangesWithIncludeMetadataChanges:
  129. (BOOL)includeMetadataChanges {
  130. if (includeMetadataChanges && _snapshot.excludes_metadata_changes()) {
  131. FSTThrowInvalidArgument(
  132. @"To include metadata changes with your document changes, you must call "
  133. @"addSnapshotListener(includeMetadataChanges: true).");
  134. }
  135. if (!_documentChanges || _documentChangesIncludeMetadataChanges != includeMetadataChanges) {
  136. _documentChanges = [FIRDocumentChange documentChangesForSnapshot:_snapshot
  137. includeMetadataChanges:includeMetadataChanges
  138. firestore:self.firestore];
  139. _documentChangesIncludeMetadataChanges = includeMetadataChanges;
  140. }
  141. return _documentChanges;
  142. }
  143. @end
  144. NS_ASSUME_NONNULL_END