Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSMutableDictionary & dispatch_async Native Objects C# equivalent or similar

I'm fairly new to xamarin and mobile dev. I'm currently migrating geofire library by Firebase to xamarin.ios. I came across the following objective-c code and trying to figure out what is actually doing? and its c# equivalent:

@property (nonatomic, strong) NSMutableDictionary *keyEnteredObservers;

...

GFQueryLocationInfo *info = self.locationInfos[key];

[self.keyEnteredObservers enumerateKeysAndObjectsUsingBlock:^(id observerKey,
                                                                      GFQueryResultBlock block,
                                                                      BOOL *stop) {
        dispatch_async(self.geoFire.callbackQueue, ^{         // the callbackQueue is of type @property (nonatomic, strong) dispatch_queue_t callbackQueue;
            block(key, info.location);
        });
    }];

for the callbackQueue I am currently using type BlockingCollection<'Task>

Any help is greatly appreciated.

like image 226
Ian Avatar asked Feb 21 '26 00:02

Ian


1 Answers

A NSMutableDictionary.enumerateKeysAndObjectsUsingBlock in this context is doing two basic things.

  • It filters the dictionary based on an key. (A Linq Where would work as a C# replacement)

  • The filtered elements of the dictionary are available to a "block" of code as it is executed asynchronously(dispatch_async) via GCD (Grand Central Dispatch). So you are already using a BlockingCollection as a Task pump, so pass the key string that is a parameter to updateLocationInfo and the CLLocation to your Task...

Note: The stop boolean will cause an early exit from the enumerator, so a C# break as a replacement, but it is not used in this context...

If you are still using a NSMutableDictionary for your observers, you can filter via KeysForObject. In my version of GeoFire, I used a BlockingCollection<Action> vs. Tasks thus added the lambdas directly to the work queue.

Something like:

foreach (var info in keyEnteredObservers.KeysForObject(firebaseHandle))
{
    var nonCapturedLocation = info.location.Copy(); // location = CLLocation, do not capture entire dictionary by ref in lambda
    callbackQueue.Add(() =>
    {
        GFQueryResultBlock(key, nonCapturedLocation);
    });
}
like image 97
SushiHangover Avatar answered Feb 23 '26 12:02

SushiHangover