locked
Overriding PerformSelector causes crash RRS feed

  • Question

  • User53685 posted

    I've tried to override PerformSelector in a couple of subclasses (of NSOutlineView and NSTextView), and both times I get a crash because apparently the object being passed to the method is null. This crash happens even with the default override code that Xamarin Studio creates. For example:

    public override NSObject PerformSelector(ObjCRuntime.Selector aSelector, NSObject anObject) { return base.PerformSelector(aSelector, anObject); }

    Here, when base.PerformSelector is called, the crash happens, saying that anObject can not be null. I'm struggling to understand why this crash would suddenly start occurring because of this override code.

    Thanks David.

    Friday, October 2, 2015 7:19 AM

Answers

  • User35201 posted

    @DavidVincent So I took a look at this issue this morning. The short answer is that it is (at least) one bug:

    https://bugzilla.xamarin.com/show_bug.cgi?id=34522

    To give you some explanation on how overriding and calling base could possibly "break" something, I'll have to tell you a bit of a story.

    Previous to ios9/OX 10.11, Apple had zero markings in many of their headers on which APIs allowed nil (sometimes the documentation helped). In many cases when you mess this up, you crash with an NSException (which you can not catch in managed code and recover from). In a few, you corrupt native state (have fun debugging that).

    To prevent C# developers from inflicting major pain upon themselves, our binding layer will catch many cases you are incorrectly passing null and throw a "nice" C# exception to prevent you from blowing up with a sea of read NSException text (that many people find scary).

    However, occasionally our bindings have bugs and incorrectly prevent you from passing null when it is actually allowed. This is the case you ran into.

    If you want to hack around this, you can do something like:

    https://gist.github.com/chamons/a1d6f56f8f9db0b9dea8

    which manually exports a new version of PerformSelector and does the message calls for you. Then you can delete the incorrect throw new ArgumentNullException case.

    In general however, you often don't need to override PerformSelector. What use case requires this?

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, October 2, 2015 2:31 PM

All replies

  • User35201 posted

    @DavidVincent So I took a look at this issue this morning. The short answer is that it is (at least) one bug:

    https://bugzilla.xamarin.com/show_bug.cgi?id=34522

    To give you some explanation on how overriding and calling base could possibly "break" something, I'll have to tell you a bit of a story.

    Previous to ios9/OX 10.11, Apple had zero markings in many of their headers on which APIs allowed nil (sometimes the documentation helped). In many cases when you mess this up, you crash with an NSException (which you can not catch in managed code and recover from). In a few, you corrupt native state (have fun debugging that).

    To prevent C# developers from inflicting major pain upon themselves, our binding layer will catch many cases you are incorrectly passing null and throw a "nice" C# exception to prevent you from blowing up with a sea of read NSException text (that many people find scary).

    However, occasionally our bindings have bugs and incorrectly prevent you from passing null when it is actually allowed. This is the case you ran into.

    If you want to hack around this, you can do something like:

    https://gist.github.com/chamons/a1d6f56f8f9db0b9dea8

    which manually exports a new version of PerformSelector and does the message calls for you. Then you can delete the incorrect throw new ArgumentNullException case.

    In general however, you often don't need to override PerformSelector. What use case requires this?

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, October 2, 2015 2:31 PM
  • User53685 posted

    Thanks Chris for a very clear and substantial answer.

    The case I have is dealing with key handling. I was trying to do it the way Apple recommended, by calling InterpretKeyEvents on the responder, and letting the command actions float up the responder chain.

    I was still able to do what I wanted, but instead of implementing PerformSelector one each in a couple of classes I had to write a separate function for every single command I wanted to catch. It's not the end of the world - it was more just very puzzling to me why the problem I outlined above was occurring.

    I guess if the bug gets fixed I could always change to what I originally intended, so I'll keep an eye on it.

    Thanks again David.

    Friday, October 2, 2015 4:56 PM
  • User53685 posted

    Hi again Chris,

    any progress on this? I see the bugzilla bug progress isn't exactly setting the world on fire. I tried the hack you suggested, but it didn't work for me at all, and it seems to me that fixing the bug might be quite simple. I managed to do some boilerplating to get around the problem the first time, but now I've run up against it again, and it's going to cause some serious complication to get things working this time.

    Cheers David.

    Saturday, November 21, 2015 5:21 PM
  • User35201 posted

    @DavidVincent Like most products, Xamarin.Mac has a backlog of bugs and feature requests that we fix in a priority queue based on severity, frequency of occurrence, and such. For this bug, you are the only person to ever hit it, and you said you had a reasonble work around.

    In either case, even if I fixed it today, it would take awhile (C7) before you'd likely see a fix. What problems are you seeing that prevents the manual exporting from working? Is there a use case that I'm not seeing that is making this more painful that first appearance?

    Monday, November 23, 2015 2:01 PM