xamarin.iosobjective-sharpiexamarin.ios-binding

Xamarin ios delegation


What is the correct way to use delegation pattern in Xamarin?

in API Definitions (generated by sharpie) I have protocol mapped to Interface SomeDelegate:

// @protocol SomeDelegate <NSObject>
    [Protocol, Model]
    [BaseType (typeof(NSObject))]
    interface SomeDelegate
    {
        // @required -(void)someMethod;
        [Abstract]
        [Export ("someMethod")]
        void SomeMethod;
        ...

I have declared view controller like this:

public partial class ViewController : UIViewController

but I can't make view controller to implement my protocol like this:(can't have multiple base classes)

public partial class ViewController : UIViewController, SomeDelegate

I can implement this delegate on some extra class:

public ViewControllerDelegate : SomeDelegate

and use this class as a delegate, but this not really convenient way for me.

I've found recently that by adding "I":

public partial class ViewController : UIViewController, ISomeDelegate

I avoid having "multiple base classes error" by (I assume) explicitly saying compiler that this is interface (protocol) not a base class.

Now I need to pass delegate as a parameter of method, and have compile error - can't convert SomeDelegate type to SomeDelegate

Is there a way to implement delegates in some classes like UIViewController (whatever) ?


Solution

  • Try this for callback/delegate in Xamarin iOS:

    Define an Interface for your method:

    public interface sampleDelegate{
        void GetSelectedItem();
    }         
    

    On your destinationViewController, declare a WeakReference of your interface and make the call:

    public partial class SuggesterTableViewController : BaseSuggesterTableViewController{
        public WeakReference <sampleDelegate> _workerDelegate;
        public SuggesterTableViewController(IntPtr handle) : base(handle){
        }
        public sampleDelegate WorkerDelegate{
            get{
                sampleDelegate workerDelegate;
                return _workerDelegate.TryGetTarget(out workerDelegate) ? workerDelegate : null;
            }
            set{
                _workerDelegate = new WeakReference<sampleDelegate>(value);
            }
        }
        public override void RowSelected(UITableView tableView, NSIndexPath indexPath){
            if (_workerDelegate != null)
                WorkerDelegate?.GetSelectedItem();
        }
    }
    

    On your sourceViewController implement the interface:

    public partial class SomeViewController : UIViewController,sampleDelegate{
        public void openSuggestorView(){
            SuggesterTableViewController suggestVC = (SuggesterTableViewController)this.Storyboard.InstantiateViewController("SuggestTableVC");
            suggestVC._workerDelegate = new WeakReference<sampleDelegate>(this);
    
        }
    
        public void GetSelectedItem(){
            Console.WriteLine("Callback called");
        }
    }