Skip to content

🐛 [cloud_firestore] iOS: Rework is incompatible with multi-isolate Apps #4108

Closed
@ened

Description

@ened

Bug report

Our iOS App runs the FG isolate (Flutter main application as usual) plus 1, sometimes 2, long-lived isolates in the background.
Upon registering the Firestore plugin for the second instance, the first instance's Dart side will loose connectivity to the native side, causing Snapshot listeners functionality to stop.

We need Firestore to work in both isolates, as one of them revolves about listening to document changes for user requested actions and the other one is pertinent to the background functionality of our App.

Steps to reproduce

Steps to reproduce the behavior:

You will need two isolates, to test this behavior.
You can try this using flutter_workmanager or flutter_uploader.
Attempt to listen to a document snapshots stream on both references, you will find that one of them can receive contents.

Expected behavior

Both isolates will subscribe to the value and receive it equally well.

Additional context

The issue seems to stem from how the plugin is instantiated on iOS, in the registerPluginsMethod:

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
  FLTFirebaseFirestoreReaderWriter *firestoreReaderWriter = [FLTFirebaseFirestoreReaderWriter new];
  FlutterMethodChannel *channel =
      [FlutterMethodChannel methodChannelWithName:kFLTFirebaseFirestoreChannelName
                                  binaryMessenger:[registrar messenger]
                                            codec:[FlutterStandardMethodCodec
                                                      codecWithReaderWriter:firestoreReaderWriter]];

  FLTFirebaseFirestorePlugin *instance = [FLTFirebaseFirestorePlugin sharedInstance];
  instance.channel = channel;
  [registrar addMethodCallDelegate:instance channel:channel];
#if TARGET_OS_OSX
// TODO(Salakar): Publish does not exist on MacOS version of FlutterPluginRegistrar.
#else
  [registrar publish:instance];
#endif
}

Pay close attention to the line instance.channel = channel. This is correct, however - because instance is a singleton object shared among the Apps isolates (retrieved via [FLTFirebaseFirestorePlugin sharedInstance]), one isolate instantiation and the plugin initialization of will override the previous one.

I'm omitting doctor / pub output as this should be a code level issue.

This used to work in the cloud firestore version before the rework; I assume with it's own caveats.

@Salakar

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions