Bug 57650 - Sort out support for constructors declared in protocols
Summary: Sort out support for constructors declared in protocols
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: XI 10.99 (xcode9)
Hardware: Macintosh Mac OS
: --- enhancement
Target Milestone: Xcode9
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Blocks: 57735
  Show dependency tree
Reported: 2017-06-21 02:52 UTC by Miguel de Icaza [MSFT]
Modified: 2017-08-10 13:59 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Miguel de Icaza [MSFT] 2017-06-21 02:52:55 UTC
The NSItemProviderReading class exposes this method:


Which is a constructor, and we do not have a way of constructing the objects today in this way.  We would need a help method to allocate an instance of an object and call a constructor for this (for user provided implementations of this).

The flip side of the story is not a problem (or not much of one), as the method can be inlined in the places that need it.
Comment 1 Miguel de Icaza [MSFT] 2017-06-21 02:56:06 UTC
Perhaps the solution would have to be:

CreateInstance (Type t, NSData data, string identifier, out NSError error) method in some helper class, that would perform the constructor lookup, and new the instance with the specific constructor call.

I think this is the only possible solution.
Comment 2 Rolf Bjarne Kvinge [MSFT] 2017-06-21 07:10:26 UTC
We already create an _Extensions class with extension methods for optional members, we could create another method in there for required constructors.

    class INSItemProviderReading_Extensions {
        public static INSItemProviderReading CreateInstance (Type t, NSData data, string identifier, out NSError error)
            // ...

if we ever get static methods in interfaces, we can just generate this on the interface as well.

For the other side, when ObjC creates instances, we might want to teach the registrar about such constructors, so that if the user does this:

    class MyDataStore : NSObject, INSItemProviderReading {}

the registrar will show an warning/error, explaining that the constructor has to be implemented.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2017-06-21 09:57:47 UTC
This issue shows up in: https://github.com/xamarin/xamarin-macios/pull/2190
Comment 5 Miguel de Icaza [MSFT] 2017-06-24 02:55:34 UTC
Rolf, good suggestion on CreateInstance side.   The constructor is a little trickier because what is happening is that the Cocoa runtime will allocate the object and we just have to complete the initialization.

And this is perhaps the opening that we need: If we are going to add special registrar/compilation error reporting that the registrar also can also direct invocations to the "initWithItemProviderData:typeIdentifier:error:" selector to go to a constructor that matches the (NSData, string, out NSError) signature but setting the handle field before calling, so we trigger the codepath that allows us to not allocate the object instance
Comment 6 Rolf Bjarne Kvinge [MSFT] 2017-06-26 12:32:23 UTC
We already support exporting constructors to Objective-C, you just have to bind them as normal naming them as "Constructor":

	[Export ("initWithDoubleValue:unit:")]
	IntPtr Constructor (double doubleValue, NSUnit unit);

the generated code can be called from ObjC as well:

	[Export ("initWithDoubleValue:unit:")]
	public NSMeasurement (global::System.Double doubleValue, NSUnit unit)
		: base (NSObjectFlag.Empty)
		// ...

we already have magic code that detects if a handle already exists or not, and we won't call alloc when this constructor was called from ObjC.

The only problem is that user's won't have intellisense to help them write these constructors.

I'll have a look at implementing the required generator and registrar changes.
Comment 7 Rolf Bjarne Kvinge [MSFT] 2017-08-10 13:50:58 UTC
Apple solved this for us: they renamed the selector to not be a constructor anymore.