Finally figured out how delegate = self works in Xamarin.iOS

Quite often when using Xamarin.iOS (MonoTouch) you will find yourself having to port objective-c samples to C#. One thing that has always bothered me is when I find a line like this.

myTextView.delegate = self;

The solution I always go for is

myTextView.Delegate = this;

But this will cause a "Cannot implicitly convert type" compiler error. Take a look at this simple ViewController example.

public class ViewController : UIViewController
{
    public ViewController()
    {
    }
    
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        UITextView myTextView = new UITextView(new RectangleF(10, 30, 300, 50));
        myTextView.Text = "beeradmoore.com";
        View.AddSubview(myTextView);
    }
}

If I wanted to, lets say, fire a method everytime the text is changed I would normally do this.

public class MyTextViewDelegate : UITextViewDelegate
{
    ViewController _controller = null;

    public MyTextViewDelegate(ViewController controller)
    {
        _controller = controller;
    }

    public override void Changed(UITextView textView)
    {
        _controller.MyTextVeiwChanged();
    }
}

public class ViewController : UIViewController
{
    public ViewController()
    {

    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        UITextView myTextView = new UITextView(new RectangleF(10, 30, 300, 50));
        myTextView.Delegate = new MyTextViewDelegate(this);
        myTextView.Text = "beeradmoore.com";
        View.AddSubview(myTextView);
    }

    public void MyTextVeiwChanged()
    {
        // DO STUFF
    }
}

Which works great in my opinion and does what I need it to do BUT there is a better way! Rather than using myTextView.Delegate, I can actually use myTextView.WeakDelegate and set it to this. Thanks goes to Clancey on #monotouch (irc.gimp.org) IRC channel for pointing this out for me.

To make the method fire I simply need to export its selector like so.

class ViewController : UIViewController
{
    public ViewController()
    {

    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        UITextView myTextView = new UITextView(new RectangleF(10, 30, 300, 50));
        //myTextView.Delegate = new MyTextViewDelegate(this);
        myTextView.WeakDelegate = this;
        myTextView.Text = "beeradmoore.com";
        View.AddSubview(myTextView);
    }

    [Export("textViewDidChange:")]
    public void MyTextVeiwChanged()
    {
        // DO STUFF
    }
}

The key part is the "textViewDidChange:" which is the same as how the normal objective-c method name would be written. If you want to find out what other selectors to use for certain events you can just simply write UITextViewDelegate somewhere in your source code, right mouse click on it and select "Go to Declaration". This will then open the assembly browser where you can see how all the other selectors are already exported.

Assembly Browser from Xamarin.Studio