xamarin / xamarin-macios

.NET for iOS, Mac Catalyst, macOS, and tvOS provide open-source bindings of the Apple SDKs for use with .NET managed languages such as C#
Other
2.49k stars 515 forks source link

Can't override cancelOperation: for NSTableView (binding is missing?) #19002

Closed snechaev closed 1 year ago

snechaev commented 1 year ago

Steps to Reproduce

I have the following reference swift code and I'm trying to implement the same thing in xamain.mac.

class MyTableView : NSTableView {
        override func cancelOperation(_ sender: Any?) {
                // some custom processing        
                super.cancelOperation(sender)        
                // another part of custom processing
    }
}

The problem is that in the C# the NSTableView does not implement cancelOperation:(https://developer.apple.com/documentation/appkit/nsstandardkeybindingresponding/3005196-canceloperation?language=objc), so there is nothing to override.

I was able to handle the message with the direct export

    [Export("cancelOperation:")]
    private void CancelOperation(NSObject? sender)
    {
        // some custom processing
        System.Diagnostics.Debug.WriteLine("Custom processing");

        //won't compile
        //base.CancelOperation(sender);

        //crashes the app
        objc_msgSendSuper(this.SuperHandle, Selector.GetHandle("cancelOperation:"), sender?.Handle ?? NativeHandle.Zero);

        //another part of custom processing
        System.Diagnostics.Debug.WriteLine("another part of custom processing");
    }

    [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")]
    private static extern void objc_msgSendSuper(NativeHandle superReceiver, NativeHandle selector, NativeHandle value);

And then the problem is that I can't call base. I can't just write base.CancelOperation(sender) because of this is not an overridden member, but a direct export.

As a workaround I tried to use objc_msgSendSuper, but this crashes the application (most likely because I'm doing it wrong).

  1. Run the app attached
  2. Enter something into the second column of a table
  3. Press Esc
  4. App crashes (due to the objc_msgSendSuper call)

Expected Behavior

When Esc is pressed, the following should happen:

From code point of view: there is a straightforward way to implement custom handler for the cancelOperation: and then call the base implementation of this handler.

Actual Behavior

From code point of view: there is no a straightforward way to implement custom handler for the cancelOperation: .

Environment

Version information ``` Visual Studio Professional 2022 for Mac Version 17.6.3 (build 421) Installation UUID: e14ddb05-b7ff-4d93-8522-305592e486d8 Runtime .NET 7.0.3 (64-bit) Architecture: X64 Microsoft.macOS.Sdk 13.1.1007; git-rev-head:8afca776a0a96613dfb7200e0917bb57f9ed5583; git-branch:release/7.0.1xx-xcode14.2 Roslyn (Language Service) 4.6.0-3.23180.6+99e956e42697a6dd886d1e12478ea2b27cceacfa NuGet Version: 6.4.0.117 .NET SDK (x64) SDK: /usr/local/share/dotnet/sdk/7.0.307/Sdks SDK Versions: 7.0.307 7.0.306 7.0.304 7.0.302 6.0.413 6.0.412 6.0.410 6.0.408 MSBuild SDKs: /Applications/Visual Studio.app/Contents/MonoBundle/MSBuild/Current/bin/Sdks .NET Runtime (x64) Runtime: /usr/local/share/dotnet/dotnet Runtime Versions: 7.0.10 7.0.9 7.0.7 7.0.5 6.0.21 6.0.20 6.0.18 6.0.16 Xamarin.Profiler Version: 1.8.0.49 Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler Updater Version: 11 Xamarin.Android Version: 13.2.1.2 (Visual Studio Professional) Commit: xamarin-android/d17-5/a8a26c7 Android SDK: /Users/sergey/Library/Developer/Xamarin/android-sdk-macosx Supported Android versions: 12.0 (API level 31) 13.0 (API level 33) SDK Command-line Tools Version: 7.0 SDK Platform Tools Version: 33.0.3 SDK Build Tools Version: 32.0.0 Build Information: Mono: d9a6e87 Java.Interop: xamarin/java.interop/d17-5@149d70fe SQLite: xamarin/sqlite/3.40.1@68c69d8 Xamarin.Android Tools: xamarin/xamarin-android-tools/d17-5@ca1552d Microsoft Build of OpenJDK Java SDK: /Library/Java/JavaVirtualMachines/microsoft-11.jdk 11.0.16.1 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL Eclipse Temurin JDK Java SDK: /Library/Java/JavaVirtualMachines/temurin-8.jdk 1.8.0.302 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL Android SDK Manager Version: 17.6.0.50 Hash: a715dca Branch: HEAD Build date: 2023-08-02 19:04:28 UTC Android Device Manager Version: 0.0.0.1309 Hash: 06e3e77 Branch: HEAD Build date: 2023-08-02 19:04:28 UTC Xamarin Designer Version: 17.6.3.9 Hash: 2648399ae8 Branch: remotes/origin/d17-6 Build date: 2023-08-02 19:04:23 UTC Apple Developer Tools Xcode: 14.3 21812 Build: 14E222b Xamarin.Mac Version: 9.3.0.6 Visual Studio Professional Hash: 97731c92c Branch: xcode14.3 Build date: 2023-04-11 22:38:35-0400 Xamarin.iOS Version: 16.4.0.6 Visual Studio Professional Hash: 97731c92c Branch: xcode14.3 Build date: 2023-04-11 22:38:36-0400 Build Information Release ID: 1706030421 Git revision: c90350679f1b9295edc584519320b13d06489853 Build date: 2023-08-02 19:02:50+00 Build branch: release-17.6 Build lane: release-17.6 Operating System Mac OS X 13.5.0 Darwin 22.6.0 Darwin Kernel Version 22.6.0 Wed Jul 5 22:21:56 PDT 2023 root:xnu-8796.141.3~6/RELEASE_X86_64 x86_64 ```

Build Logs

msbuild.binlog.zip

Example Project (If Possible)

cancelOperationTest.zip

rolfbjarne commented 1 year ago

You made a c&p mistake in the P/Invoke, the EntryPoint must be objc_msgSendSuper, not objc_msgSend:

[DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSendSuper")]
private static extern void objc_msgSendSuper(NativeHandle superReceiver, NativeHandle selector, NativeHandle value);

with that change, your sample works for me.

snechaev commented 1 year ago

It was so stupid mistake, blame on me. Sorry for disturbing and many thanks for your help!