diff --git a/src/PassKit/PKPayLaterView.cs b/src/PassKit/PKPayLaterView.cs index 49c26d19733e..15457dc99641 100644 --- a/src/PassKit/PKPayLaterView.cs +++ b/src/PassKit/PKPayLaterView.cs @@ -1,72 +1,79 @@ -// Can be uncommented when this issue is resolved: # https://github.com/xamarin/xamarin-macios/issues/19271 +#nullable enable -// #nullable enable +#if IOS && !__MACCATALYST__ -// #if IOS && !__MACCATALYST__ +using System; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; -// using System; -// using System.Runtime.InteropServices; -// using System.Runtime.CompilerServices; -// using ObjCRuntime; -// using Foundation; -// using PassKit; +using Foundation; +using ObjCRuntime; +using PassKit; -// #if !NET -// using NativeHandle = System.IntPtr; -// #endif +namespace PassKit { -// namespace PassKit { + /// The delegate that is called when has determined whether the Pay Later Merchandising information is valid. + /// True if the Pay Later Merchandising information is valid, false otherwise. + public delegate void PKPayLaterViewValidateAmountCallback (bool eligible); -// public partial class PKPayLaterView { + public partial class PKPayLaterView { + [UnmanagedCallersOnly] + static void TrampolineValidateAmount (IntPtr block, byte eligible) + { + var del = BlockLiteral.GetTarget (block); + if (del is not null) { + del (eligible != 0); + } + } -// #if !NET -// delegate void PKPayLaterValidateAmountCompletionHandler (IntPtr block, byte eligible); -// static PKPayLaterValidateAmountCompletionHandler static_ValidateAmount = TrampolineValidateAmount; + /// Checks whether the Pay Later Merchandising information is valid for the specified amount and currency. + /// The amount to check for. + /// The ISO 4217 currency code to use. + /// The delegate that will be called with the result. + [SupportedOSPlatform ("ios17.0")] + [UnsupportedOSPlatform ("maccatalyst")] + [UnsupportedOSPlatform ("macos")] + [UnsupportedOSPlatform ("tvos")] + [BindingImpl (BindingImplOptions.Optimizable)] + public static void ValidateAmount (NSDecimalNumber amount, string currencyCode, PKPayLaterViewValidateAmountCallback callback) + { + if (callback is null) + ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (callback)); -// [MonoPInvokeCallback (typeof (PKPayLaterValidateAmountCompletionHandler))] -// #else -// [UnmanagedCallersOnly] -// #endif -// static void TrampolineValidateAmount (IntPtr block, byte eligible) -// { -// var del = BlockLiteral.GetTarget> (block); -// if (del is not null) { -// del (eligible != 0); -// } -// } + unsafe { + delegate* unmanaged trampoline = &TrampolineValidateAmount; + using var block = new BlockLiteral (trampoline, callback, typeof (PKPayLaterView), nameof (TrampolineValidateAmount)); + var nsCurrencyCodePtr = NSString.CreateNative (currencyCode); + try { + PKPayLaterValidateAmount (amount.Handle, nsCurrencyCodePtr, &block); + } finally { + NSString.ReleaseNative (nsCurrencyCodePtr); + } + } + } -// #if NET -// [SupportedOSPlatform ("ios17.0")] -// [UnsupportedOSPlatform ("maccatalyst")] -// [UnsupportedOSPlatform ("macos")] -// [UnsupportedOSPlatform ("tvos")] -// #endif -// [BindingImpl (BindingImplOptions.Optimizable)] -// public static void ValidateAmount (NSDecimalNumber amount, string currencyCode, Action callback) -// { -// if (callback is null) -// ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (callback)); + /// Checks whether the Pay Later Merchandising information is valid for the specified amount and currency. + /// The amount to check for. + /// The ISO 4217 currency code to use. + /// The delegate that will be called with the result. + [SupportedOSPlatform ("ios17.0")] + [UnsupportedOSPlatform ("maccatalyst")] + [UnsupportedOSPlatform ("macos")] + [UnsupportedOSPlatform ("tvos")] + [BindingImpl (BindingImplOptions.Optimizable)] + public static void ValidateAmount (decimal amount, string currencyCode, PKPayLaterViewValidateAmountCallback callback) + { + using var decimalAmount = new NSDecimalNumber ((NSDecimal) amount); + ValidateAmount (decimalAmount, currencyCode, callback); + } -// unsafe { -// #if NET -// delegate* unmanaged trampoline = &TrampolineValidateAmount; -// using var block = new BlockLiteral (trampoline, callback, typeof (PKPayLaterView), nameof (TrampolineValidateAmount)); -// #else -// using var block = new BlockLiteral (); -// block.SetupBlockUnsafe (static_ValidateAmount, callback); -// #endif -// var nsCurrencyCodePtr = NSString.CreateNative (currencyCode); -// try { -// PKPayLaterValidateAmount (amount.Handle, nsCurrencyCodePtr, &block); -// } finally { -// NSString.ReleaseNative (nsCurrencyCodePtr); -// } -// } -// } + [SupportedOSPlatform ("ios17.0")] + [UnsupportedOSPlatform ("maccatalyst")] + [UnsupportedOSPlatform ("macos")] + [UnsupportedOSPlatform ("tvos")] + [DllImport (Constants.PassKitLibrary)] + unsafe static extern void PKPayLaterValidateAmount (IntPtr /* NSDecimalNumber */ amount, IntPtr /* NSString */ currencyCode, BlockLiteral* callback); + } +} -// [DllImport (Constants.PassKitLibrary)] -// unsafe static extern void PKPayLaterValidateAmount (IntPtr /* NSDecimalNumber */ amount, IntPtr /* NSString */ currencyCode, BlockLiteral* callback); -// } -// } - -// #endif +#endif diff --git a/tests/monotouch-test/PassKit/PKPayLaterViewTest.cs b/tests/monotouch-test/PassKit/PKPayLaterViewTest.cs index 54ab17be2f74..3dafe6dec6b0 100644 --- a/tests/monotouch-test/PassKit/PKPayLaterViewTest.cs +++ b/tests/monotouch-test/PassKit/PKPayLaterViewTest.cs @@ -1,31 +1,55 @@ -// Can be uncommented when this issue is resolved: # https://github.com/xamarin/xamarin-macios/issues/19271 +#if __IOS__ && !__MACCATALYST__ -// #if __IOS__ && !__MACCATALYST__ +using System; +using System.Threading; -// using System; -// using Foundation; -// using UIKit; -// using PassKit; -// using NUnit.Framework; +using Foundation; +using UIKit; -// namespace MonoTouchFixtures.PassKit { +using PassKit; -// [TestFixture] -// [Preserve (AllMembers = true)] -// public class PKPayLaterViewTest { +using NUnit.Framework; -// [Test] -// public void ValidateAmountTest () -// { -// TestRuntime.AssertXcodeVersion (15, 0); +namespace MonoTouchFixtures.PassKit { -// for (int i = 0; i < 1000; i++){ -// PKPayLaterView.ValidateAmount (new NSDecimalNumber (i), "USD", (eligible) => { -// Assert.False (eligible); -// }); -// } -// } -// } -// } + [TestFixture] + [Preserve (AllMembers = true)] + public class PKPayLaterViewTest { -// #endif + [Test] + public void ValidateAmountTest_NSDecimal () + { + TestRuntime.AssertXcodeVersion (15, 0); + + var counter = 100; + var cnt = 0; + for (int i = 0; i < counter; i++) { + PKPayLaterView.ValidateAmount (new NSDecimalNumber (i), "USD", (eligible) => { + Interlocked.Increment (ref cnt); + }); + } + // The callback is rarely called, so just assert that we don't get more callbacks than + // actual validation requests. + Assert.That (cnt, Is.Not.LessThan (0).And.Not.GreaterThan (counter), $"NSDecimalNumber overload"); + } + + [Test] + public void ValidateAmountTest_Decimal () + { + TestRuntime.AssertXcodeVersion (15, 0); + + var counter = 100; + var cnt = 0; + for (int i = 0; i < counter; i++) { + PKPayLaterView.ValidateAmount (i, "USD", (eligible) => { + Interlocked.Increment (ref cnt); + }); + } + // The callback is rarely called, so just assert that we don't get more callbacks than + // actual validation requests. + Assert.That (cnt, Is.Not.LessThan (0).And.Not.GreaterThan (counter), $"decimal overload"); + } + } +} + +#endif diff --git a/tests/xtro-sharpie/api-annotations-dotnet/iOS-PassKit.ignore b/tests/xtro-sharpie/api-annotations-dotnet/iOS-PassKit.ignore index a4d141ea5e35..1be18a80705a 100644 --- a/tests/xtro-sharpie/api-annotations-dotnet/iOS-PassKit.ignore +++ b/tests/xtro-sharpie/api-annotations-dotnet/iOS-PassKit.ignore @@ -6,6 +6,3 @@ # needed to allow our WeakDelegate wrap !extra-null-allowed! 'System.Void PassKit.PKPayLaterView::set_WeakDelegate(Foundation.NSObject)' has a extraneous [NullAllowed] on parameter #0 - -# https://github.com/xamarin/xamarin-macios/issues/19271 -!missing-pinvoke! PKPayLaterValidateAmount is not bound