@@ -520,30 +520,34 @@ - (BFTask *)findAsyncForQueryState:(PFQueryState *)queryState
520
520
@strongify (self);
521
521
PFConstraintMatcherBlock matcherBlock = [self .offlineQueryLogic createMatcherForQueryState: queryState user: user];
522
522
523
- BFTask *checkAllObjectsTask = [BFTask taskWithResult: nil ];
524
- for (NSString *uuid in task.result ) {
525
- __block PFObject *object = nil ;
526
-
527
- checkAllObjectsTask = [[[[checkAllObjectsTask continueWithSuccessBlock: ^id (BFTask *task) {
528
- return [self _getPointerAsyncWithUUID: uuid database: database];
529
- }] continueWithSuccessBlock: ^id (BFTask *task) {
530
- object = task.result ;
531
- return [self fetchObjectLocallyAsync: object database: database];
532
- }] continueWithSuccessBlock: ^id (BFTask *task) {
533
- if (!object.dataAvailable ) {
534
- return @NO ;
523
+ BFTask *checkAllTask = [BFTask taskWithResult: nil ];
524
+ NSArray *uuidBatches = [PFInternalUtils arrayBySplittingArray: task.result withMaximumComponentsPerSegment: 64 ];
525
+ for (NSArray *uuids in uuidBatches) {
526
+ checkAllTask = [[checkAllTask continueWithSuccessBlock: ^id (BFTask *_) {
527
+ return [self _getObjectPointersAsyncWithUUIDs: uuids fromDatabase: database];
528
+ }] continueWithSuccessBlock: ^id (BFTask PF_GENERIC (NSArray <PFObject *> *)*task) {
529
+ BFTask *checkBatchTask = [BFTask taskWithResult: nil ];
530
+ for (PFObject *object in task.result ) {
531
+ checkBatchTask = [[[checkBatchTask continueWithSuccessBlock: ^id (BFTask *_) {
532
+ return [self fetchObjectLocallyAsync: object database: database];
533
+ }] continueWithSuccessBlock: ^id (BFTask *_) {
534
+ if (!object.dataAvailable ) {
535
+ return nil ;
536
+ }
537
+ return matcherBlock (object, database);
538
+ }] continueWithSuccessBlock: ^id (BFTask *task) {
539
+ if ([task.result boolValue ]) {
540
+ [mutableResults addObject: object];
541
+ }
542
+ return nil ;
543
+ }];
535
544
}
536
- return matcherBlock (object, database);
537
- }] continueWithSuccessBlock: ^id (BFTask *task) {
538
- if ([task.result boolValue ]) {
539
- [mutableResults addObject: object];
540
- }
541
- return nil ;
545
+ return checkBatchTask;
542
546
}];
543
547
}
544
- return checkAllObjectsTask ;
548
+ return checkAllTask ;
545
549
}];
546
- }] continueWithSuccessBlock: ^id (BFTask *task ) {
550
+ }] continueWithSuccessBlock: ^id (BFTask *_ ) {
547
551
@strongify (self);
548
552
549
553
// Sort, Apply Skip and Limit
@@ -561,7 +565,7 @@ - (BFTask *)findAsyncForQueryState:(PFQueryState *)queryState
561
565
ofQueryState: queryState
562
566
inDatabase: database];
563
567
564
- return [fetchIncludesTask continueWithSuccessBlock: ^id (BFTask *task ) {
568
+ return [fetchIncludesTask continueWithSuccessBlock: ^id (BFTask *_ ) {
565
569
return results;
566
570
}];
567
571
}];
@@ -867,6 +871,8 @@ - (BFTask *)getOrCreateUUIDAsyncForObject:(PFObject *)object
867
871
return tcs.task ;
868
872
}
869
873
874
+ #pragma mark Pointers
875
+
870
876
/* !
871
877
Gets an unfetched pointer to an object in the database, based on its uuid. The object may or may
872
878
not be in memory, but it must be in database. If it is already in memory, the instance will be
@@ -877,8 +883,7 @@ - (BFTask *)getOrCreateUUIDAsyncForObject:(PFObject *)object
877
883
@param database The database instance to retrieve from.
878
884
@returns The object with that UUID.
879
885
*/
880
- - (BFTask *)_getPointerAsyncWithUUID : (NSString *)uuid
881
- database : (PFSQLiteDatabase *)database {
886
+ - (BFTask *)_getPointerAsyncWithUUID : (NSString *)uuid database : (PFSQLiteDatabase *)database {
882
887
@synchronized (self.lock ) {
883
888
PFObject *existing = [self .UUIDToObjectMap objectForKey: uuid];
884
889
if (existing) {
@@ -905,24 +910,70 @@ - (BFTask *)_getPointerAsyncWithUUID:(NSString *)uuid
905
910
906
911
return nil ;
907
912
}] continueWithSuccessBlock: ^id (BFTask *_) {
908
- PFObject *pointer = nil ;
909
- @synchronized (self.lock ) {
910
- pointer = [self .UUIDToObjectMap objectForKey: uuid];
911
- if (!pointer) {
912
- pointer = [PFObject objectWithoutDataWithClassName: className objectId: objectId];
913
-
914
- // If it doesn't have objectId, we don't really need the UUID, and this simplifies some
915
- // other logic elsewhere if we only update the map for new objects.
916
- if (!objectId) {
917
- [self .UUIDToObjectMap setObject: pointer forKey: uuid];
918
- [self .objectToUUIDMap setObject: [BFTask taskWithResult: uuid] forKey: pointer];
919
- }
913
+ return [self _getOrCreateInMemoryPointerForObjectWithUUID: uuid parseClassName: className objectId: objectId];
914
+ }];
915
+ }
916
+
917
+ - (BFTask PF_GENERIC (NSArray <PFObject *> *)*)_getObjectPointersAsyncWithUUIDs:(NSArray PF_GENERIC (NSString *)*)uuids
918
+ fromDatabase:(PFSQLiteDatabase *)database {
919
+ NSMutableArray PF_GENERIC (PFObject *)*objects = [NSMutableArray array ];
920
+ NSMutableArray PF_GENERIC (NSString *)*missingUUIDs = [NSMutableArray array ];
921
+ @synchronized (self.lock ) {
922
+ for (NSString *uuid in uuids) {
923
+ PFObject *object = [self .UUIDToObjectMap objectForKey: uuid];
924
+ if (object) {
925
+ [objects addObject: object];
926
+ } else {
927
+ [missingUUIDs addObject: uuid];
920
928
}
921
929
}
922
- return pointer;
930
+ }
931
+ NSString *queryString = [NSString stringWithFormat: @" SELECT %@ , %@ , %@ FROM %@ WHERE %@ IN ('%@ ');" ,
932
+ PFOfflineStoreKeyOfUUID, PFOfflineStoreKeyOfObjectId, PFOfflineStoreKeyOfClassName,
933
+ PFOfflineStoreTableOfObjects, PFOfflineStoreKeyOfUUID,
934
+ [missingUUIDs componentsJoinedByString: @" ','" ]];
935
+ NSMutableArray PF_GENERIC (BFTask <PFObject *>*)*fetchPointersTasks = [NSMutableArray arrayWithCapacity: missingUUIDs.count];
936
+ return [[database executeQueryAsync: queryString withArgumentsInArray: nil block: ^id (PFSQLiteDatabaseResult *result) {
937
+ while ([result next ]) {
938
+ NSString *uuid = [result stringForColumnIndex: 0 ];
939
+ NSString *objectId = [result stringForColumnIndex: 1 ];
940
+ NSString *parseClassName = [result stringForColumnIndex: 2 ];
941
+ BFTask *task = [BFTask taskFromExecutor: [BFExecutor defaultPriorityBackgroundExecutor ] withBlock: ^id {
942
+ return [self _getOrCreateInMemoryPointerForObjectWithUUID: uuid parseClassName: parseClassName objectId: objectId];
943
+ }];
944
+ [fetchPointersTasks addObject: task];
945
+ }
946
+ return [BFTask taskForCompletionOfAllTasks: fetchPointersTasks];
947
+ }] continueWithSuccessBlock: ^id (BFTask *_) {
948
+ for (BFTask PF_GENERIC (PFObject *)*task in fetchPointersTasks) {
949
+ [objects addObject: task.result];
950
+ }
951
+ return objects;
923
952
}];
924
953
}
925
954
955
+ - (BFTask PF_GENERIC (PFObject *)*)_getOrCreateInMemoryPointerForObjectWithUUID:(NSString *)uuid
956
+ parseClassName:(NSString *)parseClassName
957
+ objectId:(NSString *)objectId {
958
+ PFObject *pointer = nil ;
959
+ @synchronized (self.lock ) {
960
+ pointer = [self .UUIDToObjectMap objectForKey: uuid];
961
+ if (!pointer) {
962
+ pointer = [PFObject objectWithoutDataWithClassName: parseClassName objectId: objectId];
963
+
964
+ // If it doesn't have objectId, we don't really need the UUID, and this simplifies some
965
+ // other logic elsewhere if we only update the map for new objects.
966
+ if (!objectId) {
967
+ [self .UUIDToObjectMap setObject: pointer forKey: uuid];
968
+ [self .objectToUUIDMap setObject: [BFTask taskWithResult: uuid] forKey: pointer];
969
+ }
970
+ }
971
+ }
972
+ return [BFTask taskWithResult: pointer];
973
+ }
974
+
975
+ #pragma mark Else
976
+
926
977
- (PFObject *)getOrCreateObjectWithoutDataWithClassName:(NSString *)className
927
978
objectId:(NSString *)objectId {
928
979
PFParameterAssert (objectId, @" objectId cannot be nil." );
0 commit comments