Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Key-Value Observing not triggering on a UIViewController subclass?

I'm trying to get notified when the title of a UIViewController changes.

I tried adding an observer to the title of a UIViewController subclass but it never gets triggered. What's strange about this, is that it works on a plain UIViewController. Am I doing something wrong?

Here's a code example explaining my issue (Xamarin.iOS C#):

using System;

using UIKit;
using System.Collections.Generic;

namespace ObserverTests
{
    public partial class ViewController : UIViewController
    {
        List<UIViewController> viewControllers = new List<UIViewController>();

        public override void ViewDidLoad()
        {
            UIViewController controller1 = new UIViewController() { Title = "Controller1" };
            UIViewController controller2 = new Test() { Title = "Controller2" };

            this.viewControllers.Add(controller1);
            this.viewControllers.Add(controller2);

            foreach(UIViewController viewController in viewControllers)
            {
                viewController.AddObserver("title", Foundation.NSKeyValueObservingOptions.New, (changes) =>
                    {
                        Console.WriteLine(viewController.Title);
                        Console.WriteLine("Title Changed!");
                    });
            }

            controller1.Title = "TitleChanged1"; // Works
            controller2.Title = "TitleChanged2"; // Fails
        }

        private class Test : UIViewController
        {
        }
    }
}
like image 714
skyjetsen Avatar asked Sep 16 '26 13:09

skyjetsen


1 Answers

In Xamarin the best way might be using inheritance and adding such a feature. For this you derive from UIViewController

public class UIObserveTitleChangedViewController : UIViewController
{
    public event TitleChangedEvent TitleChanged;
    public override string Title
    {
        get
        {
            return base.Title;
        }

        set
        {
            var oldTitle = base.Title;
            if (oldTitle == value)
                return;
            base.Title = value;
            OnTitleChanged(new TitleChangedEventArgs(value, oldTitle));
        }
    }

    protected virtual void OnTitleChanged(TitleChangedEventArgs args)
    {
        TitleChanged?.Invoke(this, args);
    }

    #region ctor
    public UIObserveTitleChangedViewController() { }
    public UIObserveTitleChangedViewController(NSCoder coder) : base(coder) { }
    protected UIObserveTitleChangedViewController(NSObjectFlag t) : base(t) { }
    protected internal UIObserveTitleChangedViewController(IntPtr handle) : base(handle) { }
    public UIObserveTitleChangedViewController(string nibName, NSBundle bundle) : base(nibName, bundle) { }
    #endregion
}

and implement missing event types

public delegate void TitleChangedEvent(object sender, TitleChangedEventArgs args);

public class TitleChangedEventArgs : EventArgs
{
    public string NewTitle { get; set; }
    public string OldTitle { get; set; }

    public TitleChangedEventArgs(string newTitle, string oldTitle)
    {
        NewTitle = newTitle;
        OldTitle = oldTitle;
    }
}

You can then subscribe to this event and get notified of changes

public partial class ViewController : UIObserveTitleChangedViewController
{
    public ViewController(IntPtr handle) : base(handle)
    {
        this.TitleChanged += ViewController_TitleChanged; // Subscribe to TitleChanged
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        Title = "Some title";            // triggers TitleChanged
        Title = "Another new title";     // triggers TitleChanged
    }

    private void ViewController_TitleChanged(object sender, TitleChangedEventArgs args)
    {
        Debug.WriteLine("Title changed from {0} to {1}", args.OldTitle, args.NewTitle);
    }
}
like image 79
Matt Avatar answered Sep 19 '26 01:09

Matt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!