-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Closed
Description
[REQUIRED] Step 2: Describe your environment
- Xcode version: 10.1 (10B61)
- Firebase SDK version: 5.16.0
- Firebase Component: Firestore (Auth, Core, Database, Firestore, Messaging, Storage, etc)
- Component version: Firebase/Firestore (5.16.0), FirebaseFirestore (= 1.0.0) from CocoaPods
[REQUIRED] Step 3: Describe the problem
There is a retain cycle identified by Xcode Instruments as shown below.
From Firestore/Source/API/FIRQuery.mm:113:
- (void)getDocumentsWithSource:(FIRFirestoreSource)source
completion:(void (^)(FIRQuerySnapshot *_Nullable snapshot,
NSError *_Nullable error))completion {
// [Snip]
__block id<FIRListenerRegistration> listenerRegistration;
FIRQuerySnapshotBlock listener = ^(FIRQuerySnapshot *snapshot, NSError *error) {
if (error) {
completion(nil, error);
return;
}
// Remove query first before passing event to user to avoid user actions affecting the
// now stale query.
dispatch_semaphore_wait(registered, DISPATCH_TIME_FOREVER);
[listenerRegistration remove];
if (snapshot.metadata.fromCache && source == FIRFirestoreSourceServer) {
completion(nil, /* [Snip NSError] */);
} else {
completion(snapshot, nil);
}
};
listenerRegistration = [self addSnapshotListenerInternalWithOptions:listenOptions
listener:listener];
dispatch_semaphore_signal(registered);
}
My reading is as follows:
FIRQuerySnapshotBlock listeneris a callback block that is given toaddSnapshotListenerInternalWithOptions.- That callback block references
__block id<FIRListenerRegistration> listenerRegistration. listenerRegistrationis the result of theaddSnapshotListenerInternalWithOptionscall, which ultimately contains a reference tolistener.- Nothing ever nils
listenerRegistration, so there is a retain cycle and a leak once the callback is complete.
I don't know enough about the code here to be sure, but my guess is that setting listenerRegistration = nil after each of the three completion() calls would fix the problem.
