One of major feature of the Monobjc bridge is the ability to expose .NET class to the Objective-C runtime: on the .NET side, the class is like any other .NET class and on the Objective-C side, the class is seen like any other Objective-C class. The Monobjc bridge provides a fine grained control on how a .NET class should be exposed in the Objective-C.

Rules to follow

The following rules apply when exposing a .NET class to Objective-C runtime:

  • The .NET class MUST be public.
  • The .NET class MUST not be static.
  • The .NET class MUST not be generic.
  • The .NET class MUST inherit from an Objective-C wrapper. Most .NET classes that are exposed are subclassing NSObject, but it can be any other Objective-C wrapper exported by the Monobjc bridge.
  • The .NET class MUST have an explicit default constructor. This is needed by the bridge to trigger the creation of the underlying native instance when the instance is created in the .NET runtime.
  • The .NET class MUST have a constructor that takes an IntPtr argument. This is needed by the bridge to allow the wrapping of an existing native instance when the instance is mapped from the Objective-C runtime.
  • The .NET class MAY exposed public instance variables. These instance variables are mapped to Objective-C instance fields with a public scope.
  • The .NET class MAY exposed public instance methods. These instance methods are mapped to Objective-C instance messages with a public scope.
  • The .NET class MAY exposed public static methods. The static methods are mapped to Objective-C class messages with a public scope.

The following code shows a .NET class exposed to Objective-C runtime:

using System;
using Monobjc.AppKit;
using Monobjc.Foundation;

namespace Monobjc.Samples.SimpleCocoaApp
{
    [ObjectiveCClass] // (1)
    public partial class HelloController : NSObject // (2)
    {
        [ObjectiveCIVar] // (3)
        public virtual NSButton helloButton {
            get { return this.GetInstanceVariable ("helloButton"); }
            set { this.SetInstanceVariable ("helloButton", value); }
        }

        [ObjectiveCIVar]
        public virtual NSMatrix messageRadio {
            get { return this.GetInstanceVariable ("messageRadio"); }
            set { this.SetInstanceVariable ("messageRadio", value); }
        }

        public HelloController() {} // (4)

        public HelloController(IntPtr nativePointer) : base(nativePointer) {} // (5)

        [ObjectiveCMessage("switchMessage:")] // (6)
        public void SwitchMessage(NSMatrix sender) // (7)
        {
            // ...
        }

        [ObjectiveCMessage("switchObject:")]
        public void SwitchObject(NSPopUpButton sender)
        {
            // ...
        }

        [ObjectiveCMessage("awakeFromNib")] // (8)
        public void AwakeFromNib()
        {
            // ...
        }
    }
}
  1. The ObjectiveCClass attribute is used to marked a class for an exposition in the Objective-C runtime. When the assembly is loaded, the Monobjc bridge searches for every class marked with an ObjectiveCClass attribute to expose it in the Objective-C runtime.
  2. A .NET class that want to be exposed to the Objective-C runtime must inherit from an Objective-C wrapper. Usually, it means inheriting from NSObject.
  3. The ObjectiveCField attribute is used to marked a public field for an exposition in the Objective-C runtime.
  4. The default constructor is mandatory. If you don't add it, the Monobjc bridge will throw an exception during the assembly loading.
  5. This contructor is also mandatory. If you don't add it, the Monobjc bridge will throw an exception during the assembly loading.
  6. The ObjectiveCMessage attribute is used to marked a public method (instance or static) for an exposition in the Objective-C runtime. The attribute's parameter is the selector that will be used as the Objective-C selector for the exposed class.
  7. The exposed method must be public (instance or static). The example is a typical method linked to a control action.
  8. For well known message, the implementation is straightforward.