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.

Installed 5.9 (Build 431) -- "Event registration is overwriting existing delegate..." error

JeffRushJeffRush USMember ✭✭✭

Code is unchanged in weeks but is now failing with the following error:

System.InvalidOperationException: Event registration is overwriting existing delegate. Either just use events or your own delegate.

It's at a line of code where I'm defining the "Scrolled" delegate for my UITableView:

_MyTables[_CurrentTableIndex].Scrolled += (object sender, EventArgs e) =>
{
...
...
}

I found a couple of posts about this error but assumed that the latest stable update fixed it. Any help appreciated...

«1

Posts

  • JeffRushJeffRush USMember ✭✭✭

    Well, if there is a bug, it hasn't reared it's ugly head in over a year of being in production. Approximately where in the video do you talk about this (the video is over an hour)? I'm in a crunch here because my users need a new build, and previously working code is no longer working. I am using Source, but I don't quite understand how Source and Scrolled can be conflicting with each other.

    _MyTables[_CurrentTableIndex].Source = new MyTable.TableSource(myList);
    _MyTables[_CurrentTableIndex].Scrolled += (object sender, EventArgs e) =>
    {
    ...
    ...
    }

    Anyway, I tried your suggestion and changed to DataSource which seems to be working. However, the same error is popping up elsewhere now. I have a UITextField where I define the ShouldChangeCharacters event:

    amountField.ShouldChangeCharacters = (textField, range, replacementString) =>
    {
    ....
    };

    At this point, I'm worried that these errors are all over the place. Do you recommend that I "downgrade" to a previous version of Xamarin?

    Thanks...

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Approximately where in the video do you talk about this (the video is over an hour)?

    ~47 minutes, but the earlier parts make it clearer by showing you how it works in Objective-C. When you have time you should try to watch it from the beginning so it all makes sense.

    At this point, I'm worried that these errors are all over the place.

    Every place you hit this is a potential bug. You should fix them all.

    That said, if you're in a crunch you shouldn't be updating your toolchain. The quickest fix is to roll back until you have time to do it right.

  • XamGuruXamGuru AUMember ✭✭

    A quick downgrade to 8.9.1.3 solved the issue for me.

  • JeffRushJeffRush USMember ✭✭✭

    Adam -- I'd like to go ahead and try to fix the issues if possible, and then roll back as a last resort. So what do you recommend instead of using ShouldChangeCharacters?

  • adamkempadamkemp USInsider, Developer Group Leader mod
    edited April 2015

    It depends on what else you're doing with that text field. You're probably setting a Delegate, right? What does that do? Can you show more code around that?

    FWIW, by inspecting the code in the Assembly Browser I see that there is a field called CheckForEventAndDelegateMismatches in UIApplication that can disable this check. You could put this in your app delegate to go back to the old behavior:

    UIApplication.CheckForEventAndDelegateMismatches = false;
    

    But again this was added to detect potential bugs so that may just be masking issues.

    EDIT: The field is a static so you shouldn't use SharedApplication. I fixed the example.

  • PAOLOSANTINONPAOLOSANTINON ITMember ✭✭

    I had this exception using a custom map in iOs. I solved it by making my map delegate null before assigning it again:

    from this:
    mapView.Delegate = new MyMapDelegate (false, true, detailCommand);
    to this:

        mapView.Delegate = null;
        mapView.Delegate = new MyMapDelegate (false, true, detailCommand);
    
  • JeffRushJeffRush USMember ✭✭✭

    Adam -- first of all, your fix works. By setting CheckForEventAndDelegateMismatches to false, the error goes away. However, I'd like to understand the cause and fix my code. I'm not doing anything too fancy inside the delegate:

    amountField.ShouldChangeCharacters = (UITextField textField, NSRange range, string replacementString) =>
    {
            string entry = textField.Text + replacementString;
            if (entry.Contains("."))
            {
                string[] number = entry.Split('.');
                if (number[0].Length > 6) return false;
                if (number[1].Length > 2) return false;
            }
            else
            {
                return entry.Length <= 6;
            }
    
            return true;
    };
    

    I have 3-4 UITextFields on the view at the same time, and they all get initialized the same way. The error only occurs when the text field receives focus.

    Paolo -- thanks for the suggestion; unfortunately, setting the delegate to null first didn't work for me.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    I think I'm missing some important code. What else do you do with amountField? It seems like something else somewhere is assigning something to either the Delegate or the WeakDelegate property of amountField. Can you find that code?

    If not then see if you can reduce this to a small solution that reproduces the exception and attach it as a .zip.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    had this exception using a custom map in iOs. I solved it by making my map delegate null before assigning it again:

    That shouldn't be necessary if your code is correct. You may just be masking a bug in your code rather than fixing it. The MKMapView class also has both events/callback properties and a Delegate property, but you can't use both of those at the same time. If you are using any of the events in the map view or assigning a callback method to any of its properties (ex: GetViewForAnnotation) and also using the Delegate property then you have a bug.

  • JeffRushJeffRush USMember ✭✭✭

    Here is the additional code. Hopefully this clears it up a bit. FYI, if I comment out the ShouldChangeCharacters delegate, the app works fine -- there are no additional run-time errors.

    private UITextField InitializeAmountField(CGRect rect)
    {
        UITextField amountField = new UITextField(rect);
        amountField.BorderStyle = UITextBorderStyle.Line;
        amountField.Font = UIFont.SystemFontOfSize(22f);
        amountField.KeyboardType = UIKeyboardType.DecimalPad;
        amountField.TextAlignment = UITextAlignment.Right;
        amountField.VerticalAlignment = UIControlContentVerticalAlignment.Center;
        amountField.TextColor = UIColor.FromRGB(0, 64, 0);
        amountField.Delegate = new CatchEnterDelegate();
        amountField.Alpha = 1;
        amountField.Text = "";
        amountField.ClearsOnBeginEditing = true;
        amountField.EditingDidEnd += (object sender, EventArgs e) =>
        {  
                SOME OTHER STUFF... 
        };
    
        amountField.EditingDidBegin += (object sender, EventArgs e) =>
        {  
                SOME OTHER STUFF... 
        };
        amountField.ShouldChangeCharacters = (UITextField textField, NSRange range, string replacementString) =>
        {
                string entry = textField.Text + replacementString;
                if (entry.Contains("."))
                {
                    string[] number = entry.Split('.');
                    if (number[0].Length > 6) return false;
                    if (number[1].Length > 2) return false;
                }
                else
                {
                    return entry.Length <= 6;
                }
                return true;
        };
    
        private class CatchEnterDelegate : UITextFieldDelegate
        {
                public override bool ShouldReturn(UITextField textField)
                {
                        textField.ResignFirstResponder();
                        return true;
                }
        }
    }
    
  • JeffRushJeffRush USMember ✭✭✭

    Thanks Adam - that worked perfectly. I was able to remove the the line setting UIApplication.CheckForEventAndDelegateMismatches to false as well. This can be marked as answered.

  • HoangNguyenHoangNguyen AUMember
    edited May 2015

    Hi, i got the same problem with the UIWebView in my custom renderer specifically this line:

    webView.ShouldStartLoad += HandleShouldStartLoad;
    

    my function:

    bool HandleShouldStartLoad (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) {
        if (request.HttpMethod == "POST" && request.MainDocumentURL.Fragment == "selectOutlet") {
            var data = new NSString (request.Body, NSStringEncoding.UTF8);
            var dataArray = data.ToString ().Split ('=');
    
            var view = Element as CTBOutletTreeView;
            view.SelectOutlet (dataArray [1]);
            return false;
        }
        return true;
    }
    

    I'm not really sure what went wrong here.

  • HoangNguyenHoangNguyen AUMember

    I fixed by seting Delegate = null;

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Anyone fixing it by nulling out the Delegate needs to take a look at where else the Delegate or Source property is being set. Assigning null to the Delegate is almost certainly not be right fix. Please read through my comments above, and if you have time watch the video I linked above to try to understand why this exception is occurring. There is a right way to fix this exception. Assigning null to the Delegate is not the right fix, though.

  • NetworkappNetworkapp NLMember ✭✭

    Same issue here with extending the Xamarin.Forms WebViewRenderer with a ShouldStartLoad and LoadFinished event. Probably a very common approach in many Xamarin.Forms projects. It's hard to follow your advise to check where Delegate is set, as these are Xamarin.Forms internals.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    For Xamarin.Forms renderers this means that you are overriding what the Forms renderer is doing, and that probably means you're breaking some stock behavior. Again, this is telling you about a bug in your code that you didn't know about.

  • BrendanMuirBrendanMuir USMember
    edited May 2015

    I just downloaded the MoibleCRM.iOS sample app and I get the same exception thrown to the application's entry point in Main.cs from within visual studio (related to the map controls). See the attached image file for a screenshot of the exception window.

    Any ideas on how to proceed?

  • adamkempadamkemp USInsider, Developer Group Leader mod

    The sample app has a bug in it. I don't have the sample app code so I can't tell you how to fix it, but it looks like a map view issue. I would guess that they have a custom renderer for a map view that is overriding the delegate (similar to the issue that @Netwerkapp had). Look for that.

  • BrendanMuirBrendanMuir USMember

    A bug in the sample app... bummer. I stepped through the code, but nothing jumped out at me. That's not saying much since I am just getting my feet wet with this stuff... and hence the interest in a sample app. Thanks for the prompt reply!

    ( If I end up figuring out a fix for the bug in the sample app, I will post it here. If someone else does and/or wants to take a stab at it... I downloaded the sample app code from here: http://xamarin.com/prebuilt/crm )

  • adamkempadamkemp USInsider, Developer Group Leader mod

    @BrendanMuir , that actually looks like a bug in Xamarin.Forms.Maps itself. I filed a bug report. In the meantime you can use the workaround above (setting UIApplication.CheckForEventAndDelegateMismatches to false).

  • BrendanMuirBrendanMuir USMember
    edited May 2015

    Adding UIApplication.CheckForEventAndDelegateMismatches=false to the Main method as the first line called at application start did the trick - thank you for the quick fix!

    If even the sample app coded by folks who know what they are doing contains some unwanted overriding of delegates.... that just goes to show how easy it is to do if you are not careful... and probably makes a strong argument for why such an exception is helpful. Thanks @adamkemp

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Yeah, this is a very easy thing to do on accident, and the bug is very subtle. That's why I lobbied for them to add this exception. It's going to be painful dealing with it for a while, but it's much better for the long term.

  • ChristineZuckermanChristineZuckerman USMember ✭✭✭

    @adamkemp I'm getting this in my Forms app in my WebViewCustomRenderer and I can't fix it using the method you described above. As a simple test case, use the WorkingWithWebview sample project (https://github.com/xamarin/xamarin-forms-samples). In the iOS BaseUrlWebViewRenderer add the following:

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            this.LoadFinished += OnLoadFinished;
        }
        private void OnLoadFinished(object sender, EventArgs eventArgs)
        {
            var i = 0;
        }
    

    and then try to run. The only delegate that is defined is the Application Delegate in Main.cs:

        static void Main (string[] args)
        {
            // if you want to use a different Application Delegate class from "AppDelegate"
            // you can specify it here.
            UIApplication.Main (args, null, "AppDelegate");
        }
    

    Why would the ApplicationDelegate impact the Webview Events? Does this mean I can't use events at all with Forms?

  • adamkempadamkemp USInsider, Developer Group Leader mod

    I answered @ChristineBlanda's question in this thread.

  • Adam,

    I am using this in my AppDelegate

    _locationManager = new CLLocationManager ();
    _locationManager.Delegate = new Helpers.CoreLocationManager ();

    and it works great, however I have another class where I need track the event for locations
    _locationManager.LocationsUpdated += this.ProcessLocationUpdate;

    I get your logic as to how using the delegate breaks the LocationsUpdated piece
    but I need access to class-related variables when I use _locationManager.LocationsUpdated

    Should I just override CoreLocationManager.ProcessLocationUpdate and pop an event for my class to listen to..is that the recommended model?

    Thanks in Advance

  • NikiNiki BGMember ✭✭✭

    That would be my suggestion. If you absolutely need the delegate, then any events should be surfaced via the delegate.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    I believe you can also have multiple instances of CLLocationManager so you could have one instance use the events and the other use the delegate. You shouldn't share the same instance between classes unless you are providing an API to control how it's accessed.

  • RobertDebaultRobertDebault USUniversity ✭✭✭

    Setting the delegate to null first fixed it for me. Thanks for posting this information I just knew I was going to being rewriting code today.....

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Once again, setting the Delegate to null first does not fix anything. You are only masking the bug. This exception is telling you that something is wrong. You need to fix the problem rather than just going back to pretending it doesn't exist.

  • RobertDebaultRobertDebault USUniversity ✭✭✭

    I understand and the bug will be fixed but I had to release this specific release today and since the code in question has been there since the first release it can wait for the next release to be fixed properly. Without this posting however it would have been much more difficult to determine what was causing the error.

  • TimothyLeeRussellTimothyLeeRussell USMember ✭✭

    Thanks @adamkemp

    I appreciate your insistence that it is masking another bug. Although setting the delegate to null seemed to fix the problem, I decided to go back and look at it further based on your comments.

    I am using a modified version of the nice BindableMapTest example for creating custom pins. One of the things that is done in the BindableMapTest example is setting a delegate and setting RegionChanged as well in OnElementChanged. I commented out RegionChanged and it had the same effect as setting the delegate to null before I created a new one.

    //mkMapView.RegionChanged += delegate
    //{
    //    if (Element == null)
    //    {
    //        return;
    //    }
    
    //    do something
    //};
    
    //mapView.Delegate = null;
    mapView.Delegate = new aMapDelegate(false, true, aDetailCommand);
    

    Also, a number of other troublesome issues seemed to disappear...so it seems that this was causing a bit of internal confusion.

    Again, thanks a lot for taking the time to explain this.

    So, going forward, I should have aMapDelegate handle RegionChanged?

  • TimothyLeeRussellTimothyLeeRussell USMember ✭✭

    @adamkemp Double thanks - I owe you a beer. PM an address to @hyperubik on twitter if you want to collect.

  • adamkempadamkemp USInsider, Developer Group Leader mod

    going forward, I should have aMapDelegate handle RegionChanged?

    Yeah, that's the right way to handle it. Alternatively you could convert to using only events/properties without a delegate.

  • infoMantisinfoMantis DEUniversity ✭✭

    Thanks for suggesting/adding this exception (and explaining why). Of course it's annoying at first, since it breaks seemingly working code. But fixing this actually fixed another problem in our code we've already had worked around. In combination with MvvmCross really weird behaviour can occur due to broken bindings.

  • kpantkpant USMember

    Thanks @adamkemp. I also modified the Bindable MapTest sample to use in my application. And it started causing issue with the update iOS(8.10.0) . I followed the same approach as @TimothyLeeRussell . Now the event overwriting issue is gone.

  • There's a bug in your bug fix. I unhook all events and then use a delegate. And get this error.

    locationManager.LocationsUpdated -= this.HandleNewCoordinatesFromStartup;

    locationManager.AllowDeferredLocationUpdatesUntil(pingDistance, pingTime);
    locationManager.Delegate = new GPSMileageLocationDelegate();

  • adamkempadamkemp USInsider, Developer Group Leader mod

    I don't know which fix you're talking about. The real fix is to not mix events and delegates period. All the other suggestions are just hacking around the problem. You just need to pick one: events or delegates. Any mixture of the two is a recipe for bugs in your code.

  • RobertPerry.6688RobertPerry.6688 USMember
    edited September 2015

    Not sure I follow. They aren't mixed. All events are unhooked before using a new delegate. I based this on your earlier post:

    Aha. There's the bug. This line:

    amountField.Delegate = new CatchEnterDelegate();
    Is undone by any of these lines:

    amountField.EditingDidEnd += ...
    amountField.EditingDidBegin += ...
    amountField.ShouldChangeCharacters = ...
    That's because the way those events and callbacks work is by creating a delegate object internally and assigning it to the Delegate property, which would overwrite your CatchEnterDelegate object. That's what the exception is telling you about.

    The result is that the ShouldReturn method in your delegate class will never be called. That is dead code.

    The fix in this case is to use the ShouldReturn property instead of the Delegate:

    amountField.ShouldReturn = textField =>
    {
    textField.ResignFirstResponder();
    return true;
    };

Sign In or Register to comment.