Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding when to use dispatch_get_main_queue and requiresMainQueueSetup by example

A while back I asked similar question here: Difference requiresMainQueueSetup and dispatch_get_main_queue?

I came back to it today and realised I did not grasp it completely yet. When we are writing react native modules for iOS there is dispatch_get_main_queue on ios side and requiresMainQueueSetup needed by react-native.

How and which one of these should be used for following packages and use cases?

asq-react-native-device - package that exports constants like bundle id

asq-react-native-sensors - package that allows to subscribe and receive data from device gyroscope and oher sensors

asq-react-native-google-sign-in - package tat exposes google sign in sdk

For all of these I receive warnings in my dev console i.e. enter image description here

So I assume requiresMainQueueSetup needs to be used regardless for all packages? I struggle to grasp when it needs to be set to YES or NO however. None of the modules are ui components, google sign in one, however, opens up safari view controller to perform oAuth, does this mean value needs to be set to YES here?

Do I need to use dispatch_get_main_queue whenever I use any of react-native resolver / rejecter bridge methods?

like image 433
Ilja Avatar asked Jun 19 '18 13:06

Ilja


1 Answers

While both methods are related to the way that RN interacts with your module, they are not the same.

+ (BOOL)requiresMainQueueSetup

This method determines if your module will be initialized on the main thread or not; in other words, if your module's constructor (init method) and the constantsToExport method will be called on the main thread.

- (dispatch_queue_t)methodQueue

This method is an override where you can tell RN which dispatch queue to use when calling your module's exported methods (exported using the RCT_EXPORT_METHOD macro). Returning dispatch_get_main_queue() here returns the main queue which belongs to the main thread, asking RN to invoke your exported methods on the main thread, but you can use any other custom dispatch queue if you have such requirement.

Main thread execution

If we're to simplify this, any operation that involves UI manipulation is required to be executed on the main thread or main dispatch queue. Even if your modules are not UI components there are other UI operations that can be executed from native modules, for example: presenting a view-controller (can be a system view-controller or a custom one)


As you see, all the warning that you get originate from the lack of requiresMainQueueSetup implementation, and it tells you the exact reason - a module is overriding the init or the constantsToExport method but doesn't specify if it wishes for it to be executed on the main thread. Up until now, modules that were overriding the init or the constantsToExport were initialized on the main thread by default, assuming that they might need access to UI elements or UIKit. In future RN versions this is going to change - these methods will get called on the main thread only if you explicitly say so.

The packages in question

It doesn't look like you're doing something in your init or constantsToExport that requires the main thread, but at the moment it's as if you are overriding requiresMainQueueSetup and returning YES. I recommend that you do override it and return NO, so you can test that everything works as expected and make sure that you won't have any surprises when RN defaults to this in your case in future RN versions.

Notice that even though these are not UI components, you sometimes do need the main thread when exported methods are called, like in asq-react-native-google-sign-in - the signIn methods are presenting and dismissing view-controllers. In this case you correctly override methodQueue and use the main queue for your exported methods.

Note that it's also possible to keep the method calls in RN background threads by not overriding methodQueue, and dispatch to the main queue yourself when necessary. For example:

dispatch_async(dispatch_get_main_queue(), ^{
    [RCTPresentedViewController() dismissViewControllerAnimated:YES completion:nil];
});
like image 97
Artal Avatar answered Nov 15 '22 20:11

Artal