Binding native library, initialisation constructor not called

AbhimanyuSinghal.9962AbhimanyuSinghal.9962 USMember ✭✭
edited May 14 in Xamarin.iOS

Hello everyone,

I am quite new to binding native library and unfortunately (:P) I am trying to bind a native library using Objective Sharpie. The library is a custom keyboard for which I have to inherit an iOS keyboard extension class KeyboardViewController.cs from the library class. Following is the code generated in ApiDefinition.

// @interface BLKeyboardViewController : KeyboardViewController <BLSuggestionsBannerDelegate>
    [BaseType(typeof(KeyboardViewController))]
    [Protocol]
    interface BLKeyboardViewController : BLSuggestionsBannerDelegate
    {
        // -(instancetype _Nonnull)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil __attribute__((objc_designated_initializer));
        [Export("initWithNibName:bundle:")]
        [DesignatedInitializer]
        IntPtr Constructor([NullAllowed] string nibNameOrNil, [NullAllowed] NSBundle nibBundleOrNil);

        // -(instancetype _Nullable)initWithCoder:(NSCoder * _Nonnull)coder __attribute__((objc_designated_initializer));
        [Export("initWithCoder:")]
        [DesignatedInitializer]
        IntPtr Constructor(NSCoder coder);
    }

Following is the code generated in the .g.cs file

[Protocol()]
    [Register("BobbleKeyboardViewController", true)]
    public unsafe partial class BobbleKeyboardViewController : BLKeyboardViewController, IBobbleKeyboardViewController {

        [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
        static readonly IntPtr class_ptr = Class.GetHandle ("BobbleKeyboardViewController");

        public override IntPtr ClassHandle { get { return class_ptr; } }

        [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        [Export ("init")]
        public BobbleKeyboardViewController () : base (NSObjectFlag.Empty)
        {
            IsDirectBinding = GetType ().Assembly == global::ApiDefinition.Messaging.this_assembly;
            if (IsDirectBinding) {
                InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSend (this.Handle, global::ObjCRuntime.Selector.GetHandle ("init")), "init");
            } else {
                InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSendSuper (this.SuperHandle, global::ObjCRuntime.Selector.GetHandle ("init")), "init");
            }
        }

        [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
        [DesignatedInitializer]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        [Export ("initWithCoder:")]
        public BobbleKeyboardViewController (NSCoder coder) : base (NSObjectFlag.Empty)
        {

            IsDirectBinding = GetType ().Assembly == global::ApiDefinition.Messaging.this_assembly;
            if (IsDirectBinding) {
                InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle ("initWithCoder:"), coder.Handle), "initWithCoder:");
            } else {
                InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle ("initWithCoder:"), coder.Handle), "initWithCoder:");
            }
        }

        [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected BobbleKeyboardViewController (NSObjectFlag t) : base (t)
        {
            IsDirectBinding = GetType ().Assembly == global::ApiDefinition.Messaging.this_assembly;
        }

        [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected internal BobbleKeyboardViewController (IntPtr handle) : base (handle)
        {
            IsDirectBinding = GetType ().Assembly == global::ApiDefinition.Messaging.this_assembly;
        }

        [Export ("initWithNibName:bundle:")]
        [DesignatedInitializer]
        [BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
        public BobbleKeyboardViewController (string nibNameOrNil, NSBundle nibBundleOrNil)
            : base (NSObjectFlag.Empty)
        {
            var nsnibNameOrNil = NSString.CreateNative (nibNameOrNil);

            IsDirectBinding = GetType ().Assembly == global::ApiDefinition.Messaging.this_assembly;
            if (IsDirectBinding) {
                InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSend_IntPtr_IntPtr (this.Handle, Selector.GetHandle ("initWithNibName:bundle:"), nsnibNameOrNil, nibBundleOrNil == null ? IntPtr.Zero : nibBundleOrNil.Handle), "initWithNibName:bundle:");
            } else {
                InitializeHandle (global::ApiDefinition.Messaging.IntPtr_objc_msgSendSuper_IntPtr_IntPtr (this.SuperHandle, Selector.GetHandle ("initWithNibName:bundle:"), nsnibNameOrNil, nibBundleOrNil == null ? IntPtr.Zero : nibBundleOrNil.Handle), "initWithNibName:bundle:");
            }
            NSString.ReleaseNative (nsnibNameOrNil);

        }

    } 

Now I have to call the following initialisation methods from my KeyboardViewController.cs. The code is from Native implementation where the KeyboardViewController inherits from the native version of the same class that I bind.

required convenience init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        self.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

I have so far tried the following ways without any luck. The constructors are not even called and my keyboard is not shown (no errors). Please let me know if I could provide more information, any help is appreciated. Thank you so much :)

public partial class KeyboardViewController : BobbleKeyboardViewController
    {
        public KeyboardViewController(NSString nibNameOrNil, NSBundle bundle) : base(nibNameOrNil, bundle)
        {
            this.Init();
        }
        public KeyboardViewController(NSCoder coder) : base(coder)
        {
            base.Init();
        }
}

Answers

  • ColeXColeX Member, Xamarin Team Xamurai
    edited May 15

    Check https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-initwithnibname to clarify the usage of those two initialisation constructor .

    This is the designated initializer for this class. When using a storyboard to define your view controller and its associated views, you never initialize your view controller class directly. Instead, view controllers are instantiated by the storyboard €”either automatically when a segue is triggered or programmatically when your app calls the instantiateViewControllerWithIdentifier: method of a storyboard object. When instantiating a view controller from a storyboard, iOS initializes the new view controller by calling its initWithCoder: method instead of this method and sets the nibName property to a nib file stored inside the storyboard.

  • AbhimanyuSinghal.9962AbhimanyuSinghal.9962 USMember ✭✭

    Hi,

    I'm sorry but I'm not sure what to make of it as I'm not using a Storyboard to initialise my extension controller, it is initialised automatically. Could you please elaborate or give me an example snippet?

    Thanks much

  • ColeXColeX Member, Xamarin Team Xamurai

    How do you call this two methods in c#? Could you attach the code?

  • AbhimanyuSinghal.9962AbhimanyuSinghal.9962 USMember ✭✭

    Like this

    public partial class KeyboardViewController : BobbleKeyboardViewController
        {
            public KeyboardViewController(NSString nibNameOrNil, NSBundle bundle) : base(nibNameOrNil, bundle)
            {
                this.Init();
            }
            public KeyboardViewController(NSCoder coder) : base(coder)
            {
                base.Init();
            }
    }
    
  • ColeXColeX Member, Xamarin Team Xamurai
    edited May 17

    Have you read how to use this library in native iOS ?

    The usage is identical in c# (just change obj-c to c#).

  • AbhimanyuSinghal.9962AbhimanyuSinghal.9962 USMember ✭✭

    Yes, I am using in library in native. The library is a custom keyboard for which I have to inherit an iOS keyboard extension class KeyboardViewController.cs from the library class, however I also need to add the two init methods. The native project doesn't work without the init methods either and I believe that I am not calling them correctly from C#.

Sign In or Register to comment.