public Task <bool> RemovePack(OfflinePack pack)
        {
            var tsc = new TaskCompletionSource <bool>();

            try {
                var mbPack = Runtime.GetNSObject <MGLOfflinePack>(pack.Handle);
                MGLOfflineStorage.SharedOfflineStorage().RemovePack(mbPack, (error) =>
                {
                    if (error == null)
                    {
                        tsc.TrySetResult(true);
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("Removing offline pack failed: " + error.LocalizedFailureReason);
                        tsc.TrySetResult(false);
                    }
                });
            }
            catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine("[Exception]: " + ex.Message);
                tsc.TrySetResult(false);
            }
            return(tsc.Task);
        }
        public Task <OfflinePack[]> GetPacks()
        {
            var tsc           = new TaskCompletionSource <OfflinePack[]>();
            var sharedStorage = MGLOfflineStorage.SharedOfflineStorage();
            var packs         = sharedStorage.Packs;

            if (packs == null)
            {
                /*
                 * This property is set to nil, indicating that the receiver does not yet know the existing packs,
                 * for an undefined amount of time starting from the moment the shared offline storage object is initialized
                 * until the packs are fetched from the database. After that point, this property is always non-nil,
                 * but it may be empty to indicate that no packs are present.
                 * To detect when the shared offline storage object has finished loading its packs property,
                 * observe KVO change notifications on the packs key path. The initial load results in an NSKeyValueChangeSetting change.
                 */
                getPacksTask        = tsc;
                packsObservingToken = sharedStorage.AddObserver("packs", NSKeyValueObservingOptions.Initial | NSKeyValueObservingOptions.New, (obj) =>
                {
                    var allPacks = sharedStorage.Packs;
                    if (allPacks != null)
                    {
                        getPacksTask?.SetResult(allPacks?.Select((arg) => arg.ToFormsPack()).ToArray());
                        packsObservingToken?.Dispose();
                        packsObservingToken = null;
                        getPacksTask        = null;
                    }
                });
            }
            else
            {
                tsc.SetResult(packs.Select((arg) => arg.ToFormsPack()).ToArray());
            }
            return(tsc.Task);
        }
        public Task <OfflinePack> DownloadMap(OfflinePackRegion formsRegion, Dictionary <string, string> packInfo, IOfflineStorageDelegate downloadDelegate = null)
        {
            this.downloadDelegate = downloadDelegate;
            var tsc    = new TaskCompletionSource <OfflinePack>();
            var region = new MGLTilePyramidOfflineRegion(
                new NSUrl(formsRegion.StyleURL),
                new MGLCoordinateBounds()
            {
                sw = TypeConverter.FromPositionToCoordinate(formsRegion.Bounds.SouthWest),
                ne = TypeConverter.FromPositionToCoordinate(formsRegion.Bounds.NorthEast)
            },
                formsRegion.MinimumZoomLevel,
                formsRegion.MaximumZoomLevel);
            NSData context = null;

            if (packInfo != null)
            {
                var keys   = new List <NSString>();
                var values = new List <NSString>();
                foreach (string key in packInfo.Keys)
                {
                    keys.Add((NSString)key);
                    values.Add((NSString)packInfo[key]);
                }
                var userInfo = NSDictionary.FromObjectsAndKeys(keys.ToArray(), values.ToArray());
                context = NSKeyedArchiver.ArchivedDataWithRootObject(userInfo);
            }

            MGLOfflineStorage.SharedOfflineStorage().AddPackForRegion(region, context, (pack, error) =>
            {
                if (error != null)
                {
                    System.Diagnostics.Debug.WriteLine("Couldn't create offline pack: " + error.LocalizedFailureReason);
                    tsc.TrySetResult(null);
                }
                else
                {
                    pack.Resume();
                    var formsPack = pack.ToFormsPack();
                    tempPacks.Add(pack.GetNativeHash(), formsPack);
                    tsc.TrySetResult(formsPack);
                }
            });

            return(tsc.Task);
        }
        public OfflinePack[] GetPacks()
        {
            var packs = MGLOfflineStorage.SharedOfflineStorage().Packs;

            return(packs?.Select((arg) => arg.ToFormsPack()).ToArray());
        }