diff --git a/src/UIKit/UIDragDropSessionExtensions.cs b/src/UIKit/UIDragDropSessionExtensions.cs index 8e63baf59ec7..c3af6a1e28cd 100644 --- a/src/UIKit/UIDragDropSessionExtensions.cs +++ b/src/UIKit/UIDragDropSessionExtensions.cs @@ -9,44 +9,49 @@ #if !TVOS -// Disable until we get around to enable + fix any issues. -#nullable disable +#nullable enable namespace UIKit { - /// Contains methods for working with drag-and-drop sessions, including a default implementation of . - /// To be added. + /// Contains extension methods for working with drag-and-drop sessions. public static class UIDragDropSessionExtensions { - /// To be added. - /// To be added. - /// To be added. - /// To be added. - /// To be added. - /// To be added. - public static NSProgress LoadObjects (this IUIDropSession session, Action completion) where T : NSObject, INSItemProviderReading + /// Loads objects of the specified type from the drop session and invokes the completion handler when done. + /// The type of objects to load from the drop session. + /// The drop session to load objects from. + /// The completion handler to invoke with the loaded objects. + /// An object that can be used to track the loading progress. + public static NSProgress LoadObjects (this IUIDropSession session, Action completion) where T : NSObject, INSItemProviderReading { + // allowing null for 'completion' doesn't make much sense, but we have tests verifying that it's allowed, + // so make the implementation work with a null 'completion' handler. + ArgumentNullException.ThrowIfNull (session); + return session.LoadObjects (new Class (typeof (T)), (v) => { var arr = v as T []; if (arr is null && v is not null) { arr = new T [v.Length]; for (int i = 0; i < arr.Length; i++) { if (v [i] is not null) - arr [i] = Runtime.ConstructNSObject (v [i].Handle); + arr [i] = Runtime.ConstructNSObject (v [i].Handle)!; } } + GC.KeepAlive (v); - completion (arr); + if (completion is not null) + completion (arr); }); } + /// Returns if the specified can instantiate items of the specified . /// The session to query. - /// The type of object to query about. - /// Returns if the specified can instantiate items of the specified . - /// To be added. - /// To be added. + /// The type of object to query about. + /// if the session can load objects of the specified type; otherwise, . public static bool CanLoadObjects (this IUIDragDropSession session, Type type) { + ArgumentNullException.ThrowIfNull (session); + ArgumentNullException.ThrowIfNull (type); + return session.CanLoadObjects (new Class (type)); } } diff --git a/tests/cecil-tests/HandleSafety.KnownFailures.cs b/tests/cecil-tests/HandleSafety.KnownFailures.cs index a12e11a75242..792a7498266a 100644 --- a/tests/cecil-tests/HandleSafety.KnownFailures.cs +++ b/tests/cecil-tests/HandleSafety.KnownFailures.cs @@ -218,7 +218,6 @@ public partial class HandleSafetyTest { "UIKit.UIAlertView..ctor (System.String, System.String, UIKit.IUIAlertViewDelegate, System.String, System.String[])", "UIKit.UIAppearance.Equals (System.Object)", "UIKit.UIContentSizeCategoryExtensions.Compare (UIKit.UIContentSizeCategory, UIKit.UIContentSizeCategory)", - "UIKit.UIDragDropSessionExtensions/<>c__DisplayClass0_0`1.b__0 (Foundation.INSItemProviderReading[])", "UIKit.UIFontFeature.ObjCRuntime.INativeObject.get_Handle ()", "UIKit.UIPasteboard.set_Images (UIKit.UIImage[])", "UIKit.UIToolbar.SetItems (UIKit.UIBarButtonItem[], System.Boolean)", diff --git a/tests/monotouch-test/UIKit/UIDragDropSessionExtensionsTest.cs b/tests/monotouch-test/UIKit/UIDragDropSessionExtensionsTest.cs index d9447955fbb9..ac85578366b8 100644 --- a/tests/monotouch-test/UIKit/UIDragDropSessionExtensionsTest.cs +++ b/tests/monotouch-test/UIKit/UIDragDropSessionExtensionsTest.cs @@ -25,12 +25,30 @@ public void LoadObjectsTest () Assert.Ignore ("Ignoring tests: Requires iOS11+"); var test = new DropSession (); + Assert.That (test.CalledCanLoadObjects, Is.False, "CalledCanLoadObjects #1"); test.CanLoadObjects (typeof (UIImage)); + Assert.That (test.CalledCanLoadObjects, Is.True, "CalledCanLoadObjects #2"); + + Assert.That (test.CalledLoadObjects, Is.False, "CalledLoadObjects #1"); test.LoadObjects (null); + Assert.That (test.CalledLoadObjects, Is.True, "CalledLoadObjects #2"); + + test.CalledLoadObjects = false; + Assert.That (test.CalledLoadObjects, Is.False, "CalledLoadObjects #1"); + var calledCallback = false; + test.LoadObjects ((arr) => { + calledCallback = true; + }); + Assert.That (calledCallback, Is.True, "calledCallback"); + Assert.That (test.CalledLoadObjects, Is.True, "CalledLoadObjects #2"); + } } class DropSession : NSObject, IUIDropSession { + public bool CalledLoadObjects; + public bool CalledCanLoadObjects; + public IUIDragSession LocalDragSession => throw new NotImplementedException (); public UIDropSessionProgressIndicatorStyle ProgressIndicatorStyle { get => throw new NotImplementedException (); set => throw new NotImplementedException (); } @@ -43,6 +61,7 @@ class DropSession : NSObject, IUIDropSession { public bool CanLoadObjects (Class itemProviderReadingClass) { + CalledCanLoadObjects = true; Assert.That (itemProviderReadingClass.Handle, Is.EqualTo (new Class (typeof (UIImage)).Handle), "UIDragDropSessionExtensionsTest did not convert the type properly for 'CanLoadObjects'."); return true; } @@ -54,7 +73,9 @@ public bool HasConformingItems (string [] typeIdentifiers) public NSProgress LoadObjects (Class itemProviderReadingClass, Action completion) { + CalledLoadObjects = true; Assert.That (itemProviderReadingClass.Handle, Is.EqualTo (new Class (typeof (UIImage)).Handle), "UIDragDropSessionExtensionsTest did not convert the type properly for 'LoadObjects'."); + completion (Array.Empty ()); return new NSProgress (); }