Forum Xamarin.iOS
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

How can I resolve iOS badge icon exception?

danielparedes97danielparedes97 Member ✭✭✭
edited February 17 in Xamarin.iOS

I have a Xamarin Forms project and I use DependencyService to call the function that set the badge of the toolbar item.

I have this error, and it causes that the app crashes sometimes.

AppCenter issue details:

SIGABRT: Object reference not set to an instance of an object

This is my method to set the badge:

public void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor)
        {
            try
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    var renderer = Platform.GetRenderer(page);
                    if (renderer == null)
                    {
                        renderer = Platform.CreateRenderer(page);
                        Platform.SetRenderer(page, renderer);
                    }
                    var vc = renderer.ViewController;

                    var rightButtomItems = vc?.ParentViewController?.NavigationItem?.RightBarButtonItems;

                    var idx = page.ToolbarItems.IndexOf(item);
                    if (rightButtomItems != null && rightButtomItems.Length > idx)
                    {
                        var barItem = rightButtomItems[idx];
                        if (barItem != null)
                        {
                            barItem.UpdateBadge(value, backgroundColor.ToUIColor(), textColor.ToUIColor());
                        }
                    }

                });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

UpdateBadge:

public static void UpdateBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor)
        {
            var bLayer = GetBadgeLayer(barButtonItem);

            if (bLayer != null)
            {
                bLayer.Hidden = string.IsNullOrEmpty(text) || text == "0";
                if (bLayer.Hidden)
                {
                    return;
                }
            }

            var textLayer = bLayer?.Sublayers?.First(p => p is CATextLayer) as CATextLayer;
            if (textLayer != null && textLayer.String != "0")
            {
                textLayer.String = text;
            }
            else
            {
                barButtonItem.AddBadge(text, backgroundColor, textColor);
            }
        }

AddBadge:

public static void AddBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor, bool filled = true, float fontSize = 11.0f)
        {

            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            CGPoint offset = CGPoint.Empty;

            if (backgroundColor == null)
                backgroundColor = UIColor.Red;

            var font = UIFont.SystemFontOfSize(fontSize);

            if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
            {
                font = UIFont.MonospacedDigitSystemFontOfSize(fontSize, UIFontWeight.Regular);
            }

            var view = barButtonItem.ValueForKey(new NSString(@"view")) as UIView;
            var bLayer = GetBadgeLayer(barButtonItem);
            bLayer?.RemoveFromSuperLayer();

            var badgeSize = text.StringSize(font);

            var height = badgeSize.Height;
            var width = badgeSize.Width + 2; /* padding */

            //make sure we have at least a circle
            if (width < height)
            {
                width = height;
            }

            //x position is offset from right-hand side
            var x = view.Frame.Width - width + offset.X;

            var badgeFrame = new CGRect(new CGPoint(x: x, y: offset.Y), size: new CGSize(width: width, height: height));

            bLayer = new CAShapeLayer();
            DrawRoundedRect(bLayer, badgeFrame, 7.0f, backgroundColor, filled);
            view.Layer.AddSublayer(bLayer);

            // Initialiaze Badge's label
            var label = new CATextLayer
            {
                String = text,
                TextAlignmentMode = CATextLayerAlignmentMode.Center,
                FontSize = font.PointSize,
                Frame = badgeFrame,
                ForegroundColor = filled ? textColor.CGColor : UIColor.White.CGColor,
                BackgroundColor = UIColor.Clear.CGColor,
                ContentsScale = UIScreen.MainScreen.Scale
            };

            label.SetFont(CGFont.CreateWithFontName(font.Name));
            bLayer.AddSublayer(label);

            // Save Badge as UIBarButtonItem property
            objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, bLayer.Handle, AssociationPolicy.RETAIN_NONATOMIC);
        }

I get the code from here:
https://github.com/CrossGeeks/ToolbarItemBadgeSample/blob/master/ToolbarItemBadgeSample/ToolbarItemBadgeSample.iOS/Utils/BarButtonItemExtensions.cs

Can anyone help me ?

Best Answer

Answers

  • shamineshamine Member ✭✭

    @LandLu Are there any other we way we c\an solve this . I am facing the same issue .
    @danielparedes97 I am facing the same issue , where you able to find the solution for the same ?

Sign In or Register to comment.