Bug 57735 - [Documentation] NSItemProviderReading requirements
Summary: [Documentation] NSItemProviderReading requirements
Status: CONFIRMED
Alias: None
Product: iOS
Classification: Xamarin
Component: Documentation (show other bugs)
Version: XI 10.99 (xcode9)
Hardware: PC Mac OS
: --- enhancement
Target Milestone: Xcode9
Assignee: Bugzilla
URL:
Depends on: 57650
Blocks:
  Show dependency tree
 
Reported: 2017-06-24 02:41 UTC by Miguel de Icaza [MSFT]
Modified: 2017-10-04 09:41 UTC (History)
5 users (show)

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


Attachments

Description Miguel de Icaza [MSFT] 2017-06-24 02:41:44 UTC
This protocol defines both a mechanism to initialize allocated objects as well as an abstract/static method (see the comments on foundation.cs).

Before we release, we need to document in the remarks section for NSItemProviderReading how user code can properly implement this for user subclasses.   We will first need to sort this out for one part of the documentation:

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

For the other part of the documentation, we can write the following:

====

Classes that adopt the NSItemProviderReading protocol will want to support the readableTypeIdentifiersForItemProvider selector, which should be a property that returns an array of strings with the uniform type idetnfiers (UTI) available from this type provider.

To do this from C#, you must create a public static property that is bound with an [Export] attribute like this:

```
class MyItemProvider : UIView, INSItemProviderReading {

    [Export ("readableTypeIdentifiersForItemProvider")]
    public static string [] ReadableTypeIdentifiersForItemProvider => return new string [] { "public.image", "public.data" }
}

```

In the above example, we created a UIView subclass that implements the INSItemProviderReading protocol and we implemented the method that will return the list of the supported data types that our view has.   

At a later point, the system might decide that it needs to create an instance of your class, and your constructor will be invoked to create an instance given a blob of data, and one of the supported type identifiers.
Comment 1 Rolf Bjarne Kvinge [MSFT] 2017-09-18 15:50:40 UTC
The API has been updated slightly in the later betas, so something like this is more accurate:

====

Classes that adopt the NSItemProviderReading protocol must support the readableTypeIdentifiersForItemProvider selector, which should be a property that returns an array of strings with the uniform type identifiers (UTI) available from this type provider.

Additionally the class must support the objectWithItemProviderData:typeIdentifier:error: selector, which is called when someone wants to create an instance of your type.

To do this from C#, you must create a public static property and a public static method that are bound with [Export] attributes like this:

```
class MyItemProvider : UIView, INSItemProviderReading {

    [Export ("readableTypeIdentifiersForItemProvider")]
    public static string [] ReadableTypeIdentifiersForItemProvider => return new string [] { "public.image", "public.data" }

    [Export ("objectWithItemProviderData:typeIdentifier:error:")]
    public static MyItemProvider GetObject (NSData data, string typeIdentifier, out NSError outError)
    {
        outError = null;
        switch (typeIdentifier) {
        case "public.image": return new ...;
        case "public.data": return new ...;
        default:
            outError = new NSError (...);
            return null;
        }
    }

```

In the above example, we created a UIView subclass that implements the INSItemProviderReading protocol and we implemented the methods that will return the list of the supported data types that our view has, and that will create an instance of your class when needed.

====

The first part (about bug #57650) is not applicable anymore, since that API was renamed/removed.
Comment 2 Ivan Icin 2017-09-30 23:57:03 UTC
This is example is not good enough.

Whatever you do in:
case "public.image": return new ...;

crashes the app unless you return null. If there is a way to avoid crash please provide a more detailed sample.
Comment 3 Ivan Icin 2017-10-01 10:38:36 UTC
Some more looking show that the crash is happening because the class must has a constructor with IntPtr. However after implementing that another problem appears - 
in PerformDrop(UIDropInteraction interaction, IUIDropSession session) session.LoadObjects<T> gets only empty items, not the items that I have returned in GetObject method above.

So definetely some more detailed explanation would be appreciated in the documentation, as this is very far from something that works.
Comment 4 Rolf Bjarne Kvinge [MSFT] 2017-10-02 11:06:29 UTC
@Ivan, can you file a new bug and attach your project, so that we can look at it?
Comment 5 Ivan Icin 2017-10-02 12:17:30 UTC
@Rolf, thanks for the quick feedback, you guys from Xamarin team are really unbeatable in that, and I appreciate it very much.

If you confirm that that's the best way to do it I can, just at this point I am not sure if it is a bug or simply a lack of documentation. As said the sample above doesn't work at all, so I had to hack something myself and maybe I did it right, maybe I did it wrong. If you are sure according to my description that this is likely a bug in Xamarin, I'll file it as a new bug, just at this point I am still not sure that it might not be just a lack of documentation (this bug).
Comment 6 Rolf Bjarne Kvinge [MSFT] 2017-10-02 12:50:44 UTC
It could be a bug or it could just be a lack of documentation; but it's easier to merge duplicate bugs in bugzilla than it is to make sense of one bug with multiple issues, so when in doubt, it's always best to file a new bug.
Comment 7 Ivan Icin 2017-10-04 09:41:54 UTC
Ok, this is the bug with sample for that, thanks: https://bugzilla.xamarin.com/show_bug.cgi?id=59944

Note You need to log in before you can comment on or make changes to this bug.