diff --git a/docs/api/Foundation/DictionaryContainer.xml b/docs/api/Foundation/DictionaryContainer.xml
deleted file mode 100644
index 25aa74135dc4..000000000000
--- a/docs/api/Foundation/DictionaryContainer.xml
+++ /dev/null
@@ -1,132 +0,0 @@
-
-
- When overridden, call the base-class constructor with a .
-
-
- When creating a strongly-typed wrapper for NSDictionary,
- subclass the DicionaryContainer and provide two constructors:
- one taking an NSDictionary (to create the wrapper) and one
- taking no arguments, which should call the base class with an
- NSMutableDictionary. Then use one of the various Get and Set
- methods exposed by this class to get and set values. This is
- how a sample class would work:
-
-
-
-
-
-
-
-
- The dictionary to be wrapped.
- When overridden, call the base-class constructor, passing the .
-
-
- When creating a strongly-typed wrapper for NSDictionary,
- subclass the DicionaryContainer and provide two constructors:
- one taking an NSDictionary (to create the wrapper) and one
- taking no arguments, which should call the base class with an
- NSMutableDictionary. Then use one of the various Get and Set
- methods exposed by this class to get and set values. This is
- how a sample class would work:
-
-
-
-
-
-
-
-
- Convenience base class used by strongly-typed classes that wrap NSDictionary-based settings.
-
-
- Many iOS and OSX APIs accept configuration options as untyped
- NSDictionary values, or return untyped NSDictionary values.
- The C# bindings offer strong-typed versions of those
- dictionaries, which allow developers to get code completion
- while passing parameters, and to extract data from return
- values. The DicionaryContainer is an abstract base class that
- encapsulates the common code to wrap NSDictionaries like this.
-
-
-
- When creating a strongly-typed wrapper for NSDictionary,
- subclass the DicionaryContainer and provide two constructors:
- one taking an NSDictionary (to create the wrapper) and one
- taking no arguments, which should call the base class with an
- NSMutableDictionary. Then use one of the various Get and Set
- methods exposed by this class to get and set values. This is
- how a sample class would work:
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/CoreFoundation/CFDictionary.cs b/src/CoreFoundation/CFDictionary.cs
index 1c2d78ac315a..176409be0ef6 100644
--- a/src/CoreFoundation/CFDictionary.cs
+++ b/src/CoreFoundation/CFDictionary.cs
@@ -31,6 +31,7 @@
#nullable enable
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Foundation;
using ObjCRuntime;
@@ -97,6 +98,20 @@ public static IntPtr GetValue (IntPtr theDict, IntPtr key)
return CFDictionaryGetValue (theDict, key);
}
+ [DllImport (Constants.CoreFoundationLibrary)]
+ unsafe extern static byte /* Boolean */ CFDictionaryGetValueIfPresent (IntPtr /* CFDictionaryRef */ theDict, IntPtr /* const void * */ key, IntPtr* /* const void * * */ value);
+
+ /// Try to get the stored value for the specified .
+ /// The dictionary whose value to get.
+ /// The key of the value to find.
+ /// Upon return, the value that was found, or if the dictionary doesn't contain a value for the specified .
+ /// if the dictionary contains the specified , otherwise.
+ public unsafe static bool TryGetValue (IntPtr dictionary, IntPtr key, out IntPtr value)
+ {
+ value = default;
+ return CFDictionaryGetValueIfPresent (dictionary, key, (IntPtr*) Unsafe.AsPointer (ref value)) != 0;
+ }
+
[DllImport (Constants.CoreFoundationLibrary)]
extern static nint CFDictionaryGetCount (IntPtr theDict);
public nint Count {
@@ -220,5 +235,18 @@ public static void SetValue (IntPtr theDict, IntPtr key, bool value)
{
SetValue (theDict, key, value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle);
}
+
+ internal static void SetValue (IntPtr theDict, INativeObject? key, INativeObject? value)
+ {
+ SetValue (theDict, key.GetHandle (), value.GetHandle ());
+ GC.KeepAlive (key);
+ GC.KeepAlive (value);
+ }
+
+ internal static void SetValue (IntPtr theDict, INativeObject? key, IntPtr value)
+ {
+ SetValue (theDict, key.GetHandle (), value);
+ GC.KeepAlive (key);
+ }
}
}
diff --git a/src/CoreVideo/CVPixelFormatDescription.cs b/src/CoreVideo/CVPixelFormatDescription.cs
index 682309eccfda..6dacff7347f2 100644
--- a/src/CoreVideo/CVPixelFormatDescription.cs
+++ b/src/CoreVideo/CVPixelFormatDescription.cs
@@ -394,6 +394,16 @@ public CVFillExtendedPixelsCallBackDataStruct? FillExtendedPixelsCallbackStruct
FillExtendedPixelsCallback = data;
}
}
+
+#if !XAMCORE_5_0
+ [Obsolete ("Use 'ComponentRangeValue' instead, the property type is incorrect for this property.")]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public CVPixelFormatComponentRange? ComponentRange {
+ get => null;
+ set { }
+ }
+#endif // !XAMCORE_5_0
+
#endif // !COREBUILD
}
}
diff --git a/src/Foundation/DictionaryContainer.cs b/src/Foundation/DictionaryContainer.cs
index aa41a4b61c0c..2ac154c6b197 100644
--- a/src/Foundation/DictionaryContainer.cs
+++ b/src/Foundation/DictionaryContainer.cs
@@ -28,6 +28,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
@@ -46,289 +47,446 @@
#nullable enable
namespace Foundation {
-
- ///
+ /// Convenience class to provide strongly-typed classes that wrap based settings.
+ ///
+ ///
+ /// Many APIs accept configuration options as untyped
+ /// values, or return untyped values.
+ /// The managed bindings offer strong-typed versions of those
+ /// dictionaries, which allow developers to get code completion
+ /// while passing parameters, and to extract data from return
+ /// values. The class is an abstract base class that
+ /// encapsulates the common code to wrap dictionaries like this.
+ ///
+ ///
+ /// When creating a strongly-typed wrapper for an ,
+ /// subclass the and provide two constructors:
+ /// one taking an (to create the wrapper) and a default
+ /// costructor. They should each call the corresponding base class () constructor.
+ /// Then use one of the various Get and Set methods exposed by this class to get and set values. This is
+ /// how a sample class would work:
+ ///
+ ///
+ /// return GetInt32Value (boolKey);
+ /// set => SetInt32Value (boolKey, value);
+ /// }
+ /// }]]>
+ ///
+ ///
[SupportedOSPlatform ("ios")]
[SupportedOSPlatform ("maccatalyst")]
[SupportedOSPlatform ("macos")]
[SupportedOSPlatform ("tvos")]
public abstract class DictionaryContainer {
#if !COREBUILD
- ///
+ /// Creates a new container for an empty .
protected DictionaryContainer ()
{
Dictionary = new NSMutableDictionary ();
}
- ///
+ /// Creates a new container wrapping the specified .
+ /// The dictionary to be wrapped.
protected DictionaryContainer (NSDictionary? dictionary)
{
Dictionary = dictionary ?? new NSMutableDictionary ();
}
/// Gets the wrapped .
- /// To be added.
- /// To be added.
+ /// The wrapped .
public NSDictionary Dictionary { get; private set; }
- /// The type of values stored in the array identified by .
- /// The identifier of the array.
- /// Retrieves the array of type T associated with .
- /// To be added.
- /// To be added.
- protected T []? GetArray (NSString key) where T : NSObject
+ static T? Create (NativeHandle handle) where T : DictionaryContainer, new()
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (handle == NativeHandle.Zero)
+ return null;
+ var dict = Runtime.GetNSObject (handle, owns: false);
+ if (dict is null)
+ return null;
+ var rv = new T ();
+ rv.Dictionary = dict;
+ return rv;
+ }
+
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// if the specified was found in the dictionary, otherwise.
+ protected T? GetNativeValue (NSString key) where T : class, INativeObject
+ {
+ if (!TryGetNativeValue (key, out var value))
+ return null;
- var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle);
+ return Runtime.GetINativeObject (value, false);
+ }
+
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The instance that was found (or if no value was found for the specified key).
+ /// This method will throw an exception if the dictionary contains a value for the specified key that is not an .
+ /// if the specified was found in the dictionary, otherwise.
+ protected bool TryGetNSObject (NSString key, [NotNullWhen (true)] out T? @object) where T : NSObject
+ {
+ @object = null;
+
+ if (!TryGetNativeValue (key, out var handle))
+ return false;
+
+ // Don't use GetNSObject, because then we don't get any type checking.
+ var value = Runtime.GetNSObject (handle, false);
+ if (value is null)
+ return false;
+ @object = value as T;
+ if (@object is null)
+ throw new InvalidOperationException (string.Format ("The stored type for the key '{0}' is not '{1}', it's '{2}' (value: {3}).", key, typeof (T), value.GetType (), value));
+
+ return true;
+ }
+
+ T? GetNSObject (NSString key) where T : NSObject
+ {
+ if (!TryGetNSObject (key, out var value))
+ return null;
+ return value;
+ }
+
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The instance that was found (or if no value was found for the specified key).
+ /// This method will throw an exception if the dictionary contains a value for the specified key that is not an .
+ /// if the specified was found in the dictionary, otherwise.
+ bool TryGetNSNumber (NSString key, [NotNullWhen (true)] out NSNumber? number)
+ {
+ return TryGetNSObject (key, out number);
+ }
+
+ /// Returns the handle associated with .
+ /// The identifier of the value to get.
+ /// The returned handle that was found (or if no value was found for the specified key).
+ /// if the specified was found in the dictionary and the found value was not , otherwise.
+ protected bool TryGetNativeValue (NSString key, out NativeHandle value)
+ {
+ var rv = TryGetNativeValue (key.GetHandle (), out value);
GC.KeepAlive (key);
+ return rv;
+ }
+
+ /// Returns the handle associated with .
+ /// The identifier of the value to get.
+ /// The returned handle that was found (or if no value was found for the specified key).
+ /// if the specified was found in the dictionary and the found value was not , otherwise.
+ bool TryGetNativeValue (NativeHandle key, out NativeHandle value)
+ {
+ if (key == IntPtr.Zero)
+ throw new ArgumentNullException (nameof (key));
+
+ value = default;
+
+ if (!CFDictionary.TryGetValue (Dictionary.Handle, key, out var handle))
+ return false;
+
+ value = handle;
+ return value != NativeHandle.Zero;
+ }
+
+ /// Returns the nullable array of associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored array of value if present in the dictionary, otherwise.
+ protected T []? GetArray (NSString key) where T : NSObject
+ {
+ if (!TryGetNativeValue (key, out var value))
+ return null;
+
return NSArray.ArrayFromHandle (value);
}
+ /// Returns the nullable array of associated with the specified .
+ /// The identifier of the value to get.
+ /// A callback to convert between the native object stored in the dictionary to the desired return type.
+ /// The stored array of value if present in the dictionary, otherwise.
protected T []? GetArray (NSString key, Func creator)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNativeValue (key, out var value))
+ return null;
- var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle);
- GC.KeepAlive (key);
return NSArray.ArrayFromHandleFunc (value, creator);
}
- /// The identifier of the int.
- /// Returns the nullable int associated with .
- /// To be added.
- /// To be added.
- protected int? GetInt32Value (NSString key)
+ /// Retrieves the array associeted with .
+ /// The identifier of the value to get.
+ /// The array associeted with .
+ protected T []? GetArrayOfDictionariesValue (NSString key) where T : DictionaryContainer, new()
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNativeValue (key, out var value))
+ return null;
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ return NSArray.ArrayFromHandleFunc (value, (handle) => Create (handle)!);
+ }
+
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected byte? GetByteValue (NSString key)
+ {
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).Int32Value;
+ return number.ByteValue;
}
- /// The identifier of the .
- /// Returns the nullable associated with .
- /// To be added.
- /// To be added.
- protected uint? GetUInt32Value (NSString key)
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected sbyte? GetSByteValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNSNumber (key, out var number))
+ return null;
+
+ return number.SByteValue;
+ }
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected short? GetInt16Value (NSString key)
+ {
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).UInt32Value;
+ return number.Int16Value;
}
- /// The identifier of the native integer.
- /// Returns the nullable native integer associated with .
- /// To be added.
- /// To be added.
- protected nint? GetNIntValue (NSString key)
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected ushort? GetUInt16Value (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNSNumber (key, out var number))
+ return null;
+
+ return number.UInt16Value;
+ }
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected int? GetInt32Value (NSString key)
+ {
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).NIntValue;
+ return number.Int32Value;
}
- /// The identifier of the nuint
- /// Returns the nullable native unsigned int associated with .
- /// To be added.
- /// To be added.
- protected nuint? GetNUIntValue (NSString key)
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected uint? GetUInt32Value (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNSNumber (key, out var number))
+ return null;
+
+ return number.UInt32Value;
+ }
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected nint? GetNIntValue (NSString key)
+ {
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).NUIntValue;
+ return number.NIntValue;
}
- /// The identifier of the long.
- /// Returns the nullable long associated with .
- /// To be added.
- /// To be added.
- protected long? GetLongValue (NSString key)
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected nuint? GetNUIntValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNSNumber (key, out var number))
+ return null;
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ return number.NUIntValue;
+ }
+
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected long? GetLongValue (NSString key)
+ {
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).Int64Value;
+ return number.Int64Value;
}
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
protected ulong? GetULongValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- if (!Dictionary.TryGetValue (key, out var value))
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).UInt64Value;
+ return number.UInt64Value;
}
- /// The identifier of the .
- /// Returns the nullable associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
protected uint? GetUIntValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).UInt32Value;
+ return number.UInt32Value;
}
- /// The identifier of the float.
- /// Returns the nullable float associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
protected float? GetFloatValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNSNumber (key, out var number))
+ return null;
+
+ return number.FloatValue;
+ }
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
+ protected nfloat? GetNFloatValue (NSString key)
+ {
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).FloatValue;
+ // we only support 64-bit architectures at the moment, so this is safe
+ Validate64BitNFloat ();
+
+ return (nfloat) number.DoubleValue;
}
- /// The identifier of the double.
- /// Returns the nullable double associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
protected double? GetDoubleValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ if (!TryGetNSNumber (key, out var number))
return null;
- return ((NSNumber) value).DoubleValue;
+ return number.DoubleValue;
}
- /// The identifier of the bool.
- /// Returns the nullable Boolean associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with the specified .
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
protected bool? GetBoolValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle);
- GC.KeepAlive (key);
- if (value == IntPtr.Zero)
+ if (!TryGetNativeValue (key, out var value))
return null;
return CFBoolean.GetValue (value);
}
/// Returns the nullable DateTime associated with .
- /// The identifier of the DateTime value.
+ /// The identifier of the value to get.
+ /// The stored value if present in the dictionary, otherwise.
+ /// The stored value must be stored as an .
protected DateTime? GetDateTimeValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle);
- GC.KeepAlive (key);
- if (value == IntPtr.Zero)
+ if (!TryGetNSObject (key, out var date))
return null;
- return (DateTime) Runtime.GetNSObject (value, false)!;
- }
-
- /// The type associated with .
- /// The identifier of the reference.
- /// Returns the native object associated with .
- /// To be added.
- /// To be added.
- protected T? GetNativeValue (NSString key) where T : class, INativeObject
- {
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- T? result = Runtime.GetINativeObject (Dictionary.LowlevelObjectForKey (key.Handle), false);
- GC.KeepAlive (key);
- return result;
+ return (DateTime) date;
}
+ /// Returns the nullable string array associated with .
+ /// The identifier of the value to get.
+ /// The stored string array value if present in the dictionary, otherwise.
protected string []? GetStringArrayValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
+ if (!TryGetNativeValue (key, out var array))
+ return null;
- var array = Dictionary.LowlevelObjectForKey (key.Handle);
- GC.KeepAlive (key);
return CFArray.StringArrayFromHandle (array)!;
}
- /// The identifier of the .
- /// Returns the associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected NSDictionary? GetNSDictionary (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- NSObject value;
- Dictionary.TryGetValue (key, out value);
- return value as NSDictionary;
+ return GetNSObject (key);
}
+ /// Returns the nullable associated with .
/// The type of keys in the stored dictionary.
- /// The type of values in the stored dictionary.
- /// The identifier of the .
- /// Returns the associated with .
- /// To be added.
- /// To be added.
+ /// The type of values in the stored dictionary.
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected NSDictionary? GetNSDictionary (NSString key)
where TKey : class, INativeObject
where TValue : class, INativeObject
+ {
+ return GetNativeValue> (key);
+ }
+
+ /// Returns an with the contents of a value type of type associated with .
+ /// The value type stored in the type .
+ /// The identifier of the value to get.
+ /// The value type initialized from the data in the , or if the specified is not present in this dictionary.
+ protected T? GetNSDataAsValueType (NSString key) where T : unmanaged
+ {
+ if (!TryGetNSObject (key, out var data))
+ return null;
+ return data.ToValueType ();
+ }
+
+ /// Sets an with the contents of a value type of type associated with .
+ /// The value type stored in the type .
+ /// The identifier of the value to get.
+ /// The value to store in the .
+ protected void SetValueTypeAsNSData (NSString key, T? value) where T : unmanaged
{
if (key is null)
throw new ArgumentNullException (nameof (key));
- NSObject value;
- Dictionary.TryGetValue (key, out value);
- return value as NSDictionary;
+ var data = NSData.CreateFromValueType (value);
+ SetNativeValue (key, data);
}
- /// The type of associated with .
- /// The identifier of the .
- /// Returns the associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected T? GetStrongDictionary<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T> (NSString key)
where T : DictionaryContainer
{
@@ -336,12 +494,13 @@ protected DictionaryContainer (NSDictionary? dictionary)
(T?) Activator.CreateInstance (typeof (T), new object [] { dict }));
}
- protected T? GetStrongDictionary (NSString? key, Func createStrongDictionary)
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// A callback to convert between an and .
+ /// The stored if present in the dictionary, otherwise.
+ protected T? GetStrongDictionary (NSString key, Func createStrongDictionary)
where T : DictionaryContainer
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
var dict = GetNSDictionary (key);
if (dict is null)
return null;
@@ -349,106 +508,78 @@ protected DictionaryContainer (NSDictionary? dictionary)
return createStrongDictionary (dict);
}
- /// The identifier of the .
- /// Returns the associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected NSString? GetNSStringValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- NSObject value;
- Dictionary.TryGetValue (key, out value);
- return value as NSString;
+ return GetNSObject (key);
}
- /// The identifier of the string.
- /// Returns the string associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected string? GetStringValue (NSString key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- NSObject value;
- if (!Dictionary.TryGetValue (key, out value))
+ if (!TryGetNativeValue (key, out var value))
return null;
- var result = CFString.FromHandle (value.Handle);
- GC.KeepAlive (value);
- return result;
+ return CFString.FromHandle (value);
}
- /// The identifier of the string.
- /// Returns the string associated with .
- /// To be added.
- /// To be added.
+ ///
protected string? GetStringValue (string key)
{
- if (key is null)
- throw new ArgumentNullException (nameof (key));
-
- var keyHandle = CFString.CreateNative (key);
- try {
- return CFString.FromHandle (CFDictionary.GetValue (Dictionary.Handle, keyHandle));
- } finally {
- CFString.ReleaseNative (keyHandle);
- }
+ using var keyHandle = new TransientCFString (key);
+ if (TryGetNativeValue ((IntPtr) keyHandle, out var value))
+ return null;
+ return CFString.FromHandle (value);
}
- /// The identifier of the .
- /// Returns the nullable associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected CGRect? GetCGRectValue (NSString key)
{
var dictValue = GetNSDictionary (key);
- CGRect value;
- if (!CGRect.TryParse (dictValue, out value))
+ if (!CGRect.TryParse (dictValue, out var value))
return null;
return value;
}
- /// The identifier of the .
- /// Returns the nullable associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected CGSize? GetCGSizeValue (NSString key)
{
var dictValue = GetNSDictionary (key);
- CGSize value;
- if (!CGSize.TryParse (dictValue, out value))
+ if (!CGSize.TryParse (dictValue, out var value))
return null;
return value;
}
- /// The identifier of the .
- /// Returns the nullable associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected CGPoint? GetCGPointValue (NSString key)
{
var dictValue = GetNSDictionary (key);
- CGPoint value;
- if (!CGPoint.TryParse (dictValue, out value))
+ if (!CGPoint.TryParse (dictValue, out var value))
return null;
return value;
}
- /// The identifier of the .
- /// Returns the nullable associated with .
- /// To be added.
- /// To be added.
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected CMTime? GetCMTimeValue (NSString key)
{
var dictValue = GetNSDictionary (key);
if (dictValue is null)
- ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (dictValue));
+ return null;
var value = CMTime.FromDictionary (dictValue);
if (value.IsInvalid)
return null;
@@ -457,92 +588,112 @@ protected DictionaryContainer (NSDictionary? dictionary)
}
#if HAS_UIKIT
+ /// Returns the nullable associated with .
+ /// The identifier of the value to get.
+ /// The stored if present in the dictionary, otherwise.
protected UIEdgeInsets? GetUIEdgeInsets (NSString key)
+ {
+ if (!TryGetNSObject (key, out var value))
+ return null;
+
+ return value.UIEdgeInsetsValue;
+ }
+#endif
+
+ bool NullCheckValueTypeAndRemoveKey ([NotNullWhen (true)] NSString key, [NotNullWhen (true)] T? valueType) where T : struct
{
if (key is null)
throw new ArgumentNullException (nameof (key));
- if (!Dictionary.TryGetValue (key, out var value))
- return null;
-
- if (value is NSValue size)
- return size.UIEdgeInsetsValue;
+ if (!valueType.HasValue)
+ RemoveValue (key);
- return null;
+ return valueType.HasValue;
}
-#endif
- bool NullCheckAndRemoveKey ([NotNullWhen (true)] NSString key, bool removeEntry)
+ bool NullCheckObjectAndRemoveKey ([NotNullWhen (true)] NSString key, [NotNullWhen (true)] object? obj)
{
if (key is null)
throw new ArgumentNullException (nameof (key));
- if (removeEntry)
+ if (obj is null)
RemoveValue (key);
- return !removeEntry;
+ return obj is not null;
}
- /// The identifier to be associated with the array.
- /// The array to be associated with .
- /// Associates the array with .
- /// To be added.
+ /// Associates the array with .
+ /// The identifier of the value to get.
+ /// The array to be associated with . Pass to remove any existing association.
protected void SetArrayValue (NSString key, NSNumber []? values)
{
- if (NullCheckAndRemoveKey (key, values is null))
+ if (NullCheckObjectAndRemoveKey (key, values))
Dictionary [key] = NSArray.FromNSObjects (values);
}
- /// The type stored by the array.
- /// The identifier to be associated with the array.
- /// The array of type to be associated with .
- /// Associates the array of type with .
- /// To be added.
+ /// Associates an array of with .
+ /// The identifier of the value to get.
+ /// The array of to be associated with . Pass to remove any existing association.
protected void SetArrayValue (NSString key, T []? values)
{
- if (NullCheckAndRemoveKey (key, values is null)) {
- var nsValues = new NSObject [values!.Length];
+ if (NullCheckObjectAndRemoveKey (key, values)) {
+ var nsValues = new NSObject [values.Length];
for (var i = 0; i < values.Length; i++)
nsValues [i] = NSObject.FromObject (values [i]);
Dictionary [key] = NSArray.FromNSObjects (nsValues);
}
}
- /// The identifier to be associated with the array.
- /// The array to be associated with .
- /// Associates the array with .
- /// To be added.
+ /// Associates a array with .
+ /// The identifier of the value to get.
+ /// The to be associated with . Pass to remove any existing association.
protected void SetArrayValue (NSString key, string []? values)
{
- if (NullCheckAndRemoveKey (key, values is null))
+ if (NullCheckObjectAndRemoveKey (key, values))
Dictionary [key] = NSArray.FromStrings (values);
}
- /// The identifier to be associated with the array.
- /// The array to be associated with .
- /// Associates the array with .
- /// To be added.
+ /// Associates an array of with .
+ /// The identifier of the value to get.
+ /// The array of to be associated with . Pass to remove any existing association.
protected void SetArrayValue (NSString key, INativeObject []? values)
{
- if (NullCheckAndRemoveKey (key, values is null)) {
- var array = CFArray.FromNativeObjects (values!);
- CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, array.Handle);
- GC.KeepAlive (key);
- GC.KeepAlive (array);
+ SetArrayValue (key, values, NativeObjectExtensions.GetHandle);
+ }
+
+ /// Associates an array of with .
+ /// The identifier of the value to get.
+ /// The array of to be associated with . Pass to remove any existing association.
+ /// A callback to convert between the array's element type to
+ protected void SetArrayValue (NSString key, T []? values, Func convert)
+ {
+ if (NullCheckObjectAndRemoveKey (key, values)) {
+ var handles = new NativeHandle [values.Length];
+ for (var i = 0; i < handles.Length; i++)
+ handles [i] = convert (values [i]);
+ var array = CFArray.FromIntPtrs (handles!);
+ CFMutableDictionary.SetValue (Dictionary.Handle, key, array);
}
}
+ /// Associates a array with .
+ /// The identifier of the value to get.
+ /// The array to be associated with . Pass to remove any existing association.
+ protected void SetArrayOfDictionariesValue (NSString key, DictionaryContainer []? values)
+ {
+ SetArrayValue (key, values, DictionaryContainerHelper.GetHandle);
+ }
+
#region Sets CFBoolean value
- /// The identifier associated with the Boolean.
- /// The nullable Boolean to be associated with .
- /// Stores the Boolean and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetBooleanValue (NSString key, bool? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue)) {
- CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, value!.Value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle);
- GC.KeepAlive (key);
+ if (NullCheckValueTypeAndRemoveKey (key, value)) {
+ var v = value.Value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle;
+ CFMutableDictionary.SetValue (Dictionary.Handle, key, v);
}
}
@@ -550,88 +701,144 @@ protected void SetBooleanValue (NSString key, bool? value)
#region Sets NSNumber value
- /// The identifier associated with the int.
- /// The nullable int to be associated with .
- /// Stores the int (or ) and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ protected void SetNumberValue (NSString key, byte? value)
+ {
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
+ }
+
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ protected void SetNumberValue (NSString key, sbyte? value)
+ {
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
+ }
+
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ protected void SetNumberValue (NSString key, short? value)
+ {
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
+ }
+
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ protected void SetNumberValue (NSString key, ushort? value)
+ {
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
+ }
+
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetNumberValue (NSString key, int? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
- /// The identifier associated with the uint.
- /// The nullable unsigned int to be associated with .
- /// Stores the unsigned int (or ) and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+
protected void SetNumberValue (NSString key, uint? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetNumberValue (NSString key, nint? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetNumberValue (NSString key, nuint? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
- /// The identifier associated with the long.
- /// The nullable long to be associated with .
- /// Stores the long (or ) and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetNumberValue (NSString key, long? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
- /// The identifier associated with the float.
- /// The nullable float to be associated with .
- /// Stores the float (or ) and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ protected void SetNumberValue (NSString key, ulong? value)
+ {
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
+ }
+
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetNumberValue (NSString key, float? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
- /// The identifier associated with the double.
- /// The nullable double to be associated with .
- /// Stores the double (or ) and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ protected void SetNumberValue (NSString key, nfloat? value)
+ {
+ // we only support 64-bit architectures at the moment, so this is safe
+ Validate64BitNFloat ();
+
+ SetNumberValue (key, (double?) value);
+ }
+
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetNumberValue (NSString key, double? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = new NSNumber (value!.Value);
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = new NSNumber (value.Value);
}
#endregion
#region Sets NSString value
- /// The identifier associated with the string.
- /// The string to be associated with .
- /// Stores the string and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetStringValue (NSString key, string? value)
{
- SetStringValue (key, value is null ? (NSString) null! : new NSString (value));
+ SetStringValue (key, (NSString?) value);
}
- /// The identifier associated with the string.
- /// The string to be associated with .
- /// Stores the string and associates it with the .
- /// To be added.
+ /// Associates a nullable with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetStringValue (NSString key, NSString? value)
{
- if (NullCheckAndRemoveKey (key, value is null))
+ if (NullCheckObjectAndRemoveKey (key, value))
Dictionary [key] = value;
}
@@ -639,25 +846,20 @@ protected void SetStringValue (NSString key, NSString? value)
#region Sets Native value
- /// To be added.
- /// To be added.
- /// To be added.
- /// To be added.
- /// To be added.
+ /// Associates a nullable value with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
+ /// Specifies whether any existing values should be removed if is .
protected void SetNativeValue (NSString key, INativeObject? value, bool removeNullValue = true)
{
- if (NullCheckAndRemoveKey (key, removeNullValue && value is null)) {
- CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, value.GetHandle ());
- GC.KeepAlive (key);
- GC.KeepAlive (value);
- }
+ if (NullCheckObjectAndRemoveKey (key, removeNullValue ? value : key /* key is just an object that's not null */))
+ CFMutableDictionary.SetValue (Dictionary.Handle, key, value);
}
#endregion
- /// The identifier of the value to be removed.
- /// Removes from the dictionary the value associated with .
- /// To be added.
+ /// Removes from the dictionary the value associated with .
+ /// The identifier of the value to get.
protected void RemoveValue (NSString key)
{
if (key is null)
@@ -668,47 +870,46 @@ protected void RemoveValue (NSString key)
#region Sets structs values
- /// The identifier associated with the .
- /// The to be associated with .
- /// Stores the and associates it with the .
- /// To be added.
+ /// Associates a nullable value with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetCGRectValue (NSString key, CGRect? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = value!.Value.ToDictionary ();
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = value.Value.ToDictionary ();
}
- /// The identifier associated with the .
- /// The to be associated with .
- /// Stores the and associates it with the .
- /// To be added.
+ /// Associates a nullable value with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetCGSizeValue (NSString key, CGSize? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = value!.Value.ToDictionary ();
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = value.Value.ToDictionary ();
}
- /// The identifier associated with the .
- /// The to be associated with .
- /// Stores the and associates it with the .
- /// To be added.
+ /// Associates a nullable value with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetCGPointValue (NSString key, CGPoint? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = value!.Value.ToDictionary ();
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = value.Value.ToDictionary ();
}
- /// The identifier associated with the .
- /// The to be associated with .
- /// Stores the and associates it with the .
- /// To be added.
+ /// Associates a nullable value with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetCMTimeValue (NSString key, CMTime? value)
{
- if (NullCheckAndRemoveKey (key, !value.HasValue))
- Dictionary [key] = value!.Value.ToDictionary ();
+ if (NullCheckValueTypeAndRemoveKey (key, value))
+ Dictionary [key] = value.Value.ToDictionary ();
}
#if HAS_UIKIT
+ /// Associates a nullable value with .
+ /// The identifier of the value to get.
+ /// The nullable value to be associated with . Pass to remove any existing association.
protected void SetUIEdgeInsets (NSString key, UIEdgeInsets? value)
{
SetNativeValue (key, value is null ? null : NSValue.FromUIEdgeInsets (value.Value));
@@ -716,6 +917,13 @@ protected void SetUIEdgeInsets (NSString key, UIEdgeInsets? value)
#endif
#endregion
#endif
+
+ unsafe static void Validate64BitNFloat ()
+ {
+ var size = sizeof (nfloat);
+ if (size != 8)
+ throw new InvalidOperationException ($"Unexpected nfloat size: {size}");
+ }
}
#if !COREBUILD
diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs
index b570a9b6d639..ea6665a39ddb 100644
--- a/src/ObjCRuntime/Runtime.cs
+++ b/src/ObjCRuntime/Runtime.cs
@@ -1718,25 +1718,44 @@ static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, NSObject.Flag
return o;
}
+ /// Wraps an unmanaged into a fully typed , or returns an existing wrapper object if one already exists.
/// Type to wrap the native object as.
- /// A pointer to an unmanaged NSObject or any class that derives from the Objective-C NSObject class.
- /// Wraps an unmanaged IntPtr into a fully typed NSObject, or returns an existing wrapper object if one already exists.
- /// An instance of the T class.
- ///
- /// Returns an instance of the T class even if the native object is not in the class hierarchy of T (no type checks).
- /// This method will fail if there already is a managed wrapper of a different (and incompatible) type for the native object.
- ///
+ /// A pointer to an unmanaged or any class that derives from the Objective-C class.
+ /// An instance of the class .
+ ///
+ /// Returns an instance of the class even if the native object is not in the class hierarchy of (no type checks).
+ /// This method will fail if there already is a managed wrapper of a different and incompatible type for the native object.
+ ///
static public T? GetNSObject (IntPtr ptr) where T : NSObject
{
- return GetNSObject (ptr, IntPtr.Zero, default (RuntimeMethodHandle));
+ return GetNSObject (ptr, IntPtr.Zero, default (RuntimeMethodHandle), false, false);
+ }
+
+ /// Wraps an unmanaged into a fully typed , or returns an existing wrapper object if one already exists.
+ /// Type to wrap the native object as.
+ /// A pointer to an unmanaged or any class that derives from the Objective-C class.
+ /// An instance of the class .
+ ///
+ /// Contrary to , this method will throw an exception if the native object's type is not compatible with .
+ /// This method will fail if there already is a managed wrapper of a different and incompatible type for the native object.
+ ///
+ // Not doing "GetNSObject(IntPtr, bool checked)" because that signature very much looks like the second parameter is an "owns" parameter, a common signatures in similar methods.
+ public static T? GetNSObjectChecked (IntPtr ptr) where T : NSObject
+ {
+ return GetNSObject (ptr, IntPtr.Zero, default (RuntimeMethodHandle), false, true);
}
static T? GetNSObject (IntPtr ptr, IntPtr sel, RuntimeMethodHandle method_handle) where T : NSObject
{
- return GetNSObject (ptr, sel, method_handle, false);
+ return GetNSObject (ptr, sel, method_handle, false, false);
}
static T? GetNSObject (IntPtr ptr, IntPtr sel, RuntimeMethodHandle method_handle, bool evenInFinalizerQueue) where T : NSObject
+ {
+ return GetNSObject (ptr, sel, method_handle, evenInFinalizerQueue, false);
+ }
+
+ static T? GetNSObject (IntPtr ptr, IntPtr sel, RuntimeMethodHandle method_handle, bool evenInFinalizerQueue, bool typeSafe) where T : NSObject
{
if (ptr == IntPtr.Zero)
return null;
@@ -1747,6 +1766,9 @@ static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, NSObject.Flag
if (obj is T o)
return o;
+ if (typeSafe && obj is not null)
+ throw new InvalidCastException ($"Unable to cast object of type '{obj.GetType ().FullName}' to type '{typeof (T).FullName}'.");
+
// We either didn't find an object, or it was of the wrong type, so we need to create a new instance.
// Try to get the managed type that correspond to this exact native type
@@ -1771,6 +1793,13 @@ static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, NSObject.Flag
target_type = typeof (NSObject);
}
+ if (typeSafe) {
+ obj = ConstructNSObject (ptr, target_type, MissingCtorResolution.ThrowConstructor1NotFound, sel, method_handle);
+ if (obj is T o2)
+ return o2;
+ throw new InvalidCastException ($"Unable to cast object of type '{obj.GetType ().FullName}' to type '{typeof (T).FullName}'.");
+ }
+
return ConstructNSObject (ptr, target_type, MissingCtorResolution.ThrowConstructor1NotFound, sel, method_handle);
}
diff --git a/src/Resources.Designer.cs b/src/Resources.Designer.cs
index 4767a7547e2e..065b18eaa7ff 100644
--- a/src/Resources.Designer.cs
+++ b/src/Resources.Designer.cs
@@ -1158,5 +1158,23 @@ internal static string BI1120 {
return ResourceManager.GetString("BI1120", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to The strong enum '{0}' is not a valid strong dictionary field for the property '{1}.{2}', because its backing type is '{3}'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries..
+ ///
+ internal static string BI1121 {
+ get {
+ return ResourceManager.GetString("BI1121", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Unable to find the corresponding NSNumber property for the type {0} in {1}.{2}.
+ ///
+ internal static string BI1122 {
+ get {
+ return ResourceManager.GetString("BI1122", resourceCulture);
+ }
+ }
}
}
diff --git a/src/Resources.resx b/src/Resources.resx
index 454bafab70d5..7b03d8c8373c 100644
--- a/src/Resources.resx
+++ b/src/Resources.resx
@@ -625,4 +625,12 @@
The type '{0}' is trying to inline the methods binding the selector '{1}' from the protocols '{2}' and '{3}', using methods with different signatures ('{4}' vs '{5}'). These methods will be ignored.
+
+ The strong enum '{0}' is not a valid strong dictionary field for the property '{1}.{2}', because its backing type is '{3}'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.
+
+
+
+ Unable to find the corresponding NSNumber property for the type {0} in {1}.{2}
+
+
diff --git a/src/bgen/Enums.cs b/src/bgen/Enums.cs
index 380af426cd75..ceb1ed3e13b1 100644
--- a/src/bgen/Enums.cs
+++ b/src/bgen/Enums.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -43,6 +44,61 @@ void CopyNativeName (ICustomAttributeProvider provider)
print ("[NativeName (\"{0}\")]", oa.NativeName);
}
+#nullable enable
+ bool IsEnumBackedByNativeType (Type type, [NotNullWhen (true)] out Type? backingFieldType)
+ {
+ backingFieldType = null;
+
+ if (!type.IsEnum)
+ return false;
+
+ var backingFieldTypeAttribute = AttributeManager.GetCustomAttribute (type);
+ if (backingFieldTypeAttribute is not null) {
+ backingFieldType = backingFieldTypeAttribute.BackingFieldType;
+ return true;
+ }
+
+ foreach (var f in type.GetFields ()) {
+ var fa = AttributeManager.GetCustomAttribute (f);
+ if (fa is null)
+ continue;
+
+ backingFieldType = TypeCache.NSString;
+ return true;
+ }
+
+ // Checking for Field attributes on the enum only works if the enum is in the current api definition we're processing.
+ // So check for the Extensions type, with GetConstant + GetValue methods, as well.
+
+ var extensionType = type.Assembly.GetType (type.FullName + "Extensions");
+ if (extensionType is null)
+ return false;
+
+ var anyPropertiesWithFields = false;
+ foreach (var p in type.GetProperties (BindingFlags.NonPublic | BindingFlags.Static)) {
+ if (!AttributeManager.HasAttribute (p))
+ continue;
+
+ anyPropertiesWithFields = true;
+ break;
+ }
+ if (!anyPropertiesWithFields)
+ return false;
+
+ var getConstantMethod = type.GetMethod ("GetConstant", BindingFlags.Public | BindingFlags.Static, new Type [] { type });
+ if (getConstantMethod is null)
+ return false;
+
+ backingFieldType = getConstantMethod.ReturnType;
+
+ var getValueMethod = type.GetMethod ("GetValue", BindingFlags.Public | BindingFlags.Static, new Type [] { backingFieldType });
+ if (getValueMethod is null)
+ return false;
+
+ return false;
+ }
+#nullable disable
+
// caller already:
// - setup the header and namespace
// - call/emit PrintPlatformAttributes on the type
@@ -168,8 +224,10 @@ void GenerateEnum (Type type)
var field = fields.FirstOrDefault ();
var fieldAttr = field.Value;
- if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out library_name, out var _))
- throw ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field.Key?.Name);
+ if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out library_name, out var _)) {
+ exceptions.Add (ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field.Key?.Name));
+ library_name = "placeholder";
+ }
}
}
diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs
index 7936a40eb12e..494e26b448de 100644
--- a/src/bgen/Generator.cs
+++ b/src/bgen/Generator.cs
@@ -1784,6 +1784,91 @@ void GenerateLibraryHandles ()
sw.Close ();
}
+ bool TryGetNSNumberStrongDictionaryMethods (Type type, [NotNullWhen (true)] out string? getter, [NotNullWhen (true)] out string? setter)
+ {
+ setter = "SetNumberValue";
+ getter = null;
+
+ if (type == TypeCache.System_SByte ||
+ type == TypeCache.System_Byte ||
+ type == TypeCache.System_Int16 ||
+ type == TypeCache.System_UInt16 ||
+ type == TypeCache.System_Int32 ||
+ type == TypeCache.System_UInt32 ||
+ type == TypeCache.System_Double
+ ) {
+ getter = "Get" + type.Name + "Value";
+ } else if (type == TypeCache.System_nint) {
+ getter = "GetNIntValue";
+ } else if (type == TypeCache.System_nuint) {
+ getter = "GetNUIntValue";
+ } else if (type == TypeCache.System_Int64) {
+ getter = "GetLongValue";
+ } else if (type == TypeCache.System_UInt64) {
+ getter = "GetULongValue";
+ } else if (type == TypeCache.System_Float) {
+ getter = "GetFloatValue";
+ } else if (type == TypeCache.System_nfloat) {
+ getter = "GetNFloatValue";
+ } else if (type == TypeCache.System_Boolean) {
+ getter = "GetBoolValue";
+ setter = "SetBooleanValue";
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool TryGetNSNumberField (Type wrappedNumberType, [NotNullWhen (true)] out string? fieldName)
+ {
+ fieldName = null;
+
+ if (wrappedNumberType == TypeCache.System_Float) {
+ fieldName = "FloatValue";
+ } else if (wrappedNumberType == TypeCache.System_Double) {
+ fieldName = "DoubleValue";
+ } else if (wrappedNumberType == TypeCache.System_nfloat) {
+ fieldName = "NFloatValue";
+ } else if (wrappedNumberType == TypeCache.System_Int32) {
+ fieldName = "Int32Value";
+ } else if (wrappedNumberType == TypeCache.System_UInt32) {
+ fieldName = "UInt32Value";
+ } else if (wrappedNumberType == TypeCache.System_Int64) {
+ fieldName = "Int64Value";
+ } else if (wrappedNumberType == TypeCache.System_UInt64) {
+ fieldName = "UInt64Value";
+ } else if (wrappedNumberType == TypeCache.System_Int16) {
+ fieldName = "Int16Value";
+ } else if (wrappedNumberType == TypeCache.System_UInt16) {
+ fieldName = "UInt16Value";
+ } else if (wrappedNumberType == TypeCache.System_SByte) {
+ fieldName = "SByteValue";
+ } else if (wrappedNumberType == TypeCache.System_Byte) {
+ fieldName = "ByteValue";
+ } else if (wrappedNumberType == TypeCache.System_Boolean) {
+ fieldName = "BoolValue";
+ } else if (wrappedNumberType == TypeCache.System_nint) {
+ fieldName = "NIntValue";
+ } else if (wrappedNumberType == TypeCache.System_nuint) {
+ fieldName = "NUIntValue";
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ void ValidateStrongEnumBackingTypeInStrongDictionaryType (PropertyInfo property, Type enumBackingType)
+ {
+ if (enumBackingType == TypeCache.NSString)
+ return;
+ if (enumBackingType == TypeCache.NSNumber)
+ return;
+
+ exceptions.Add (ErrorHelper.CreateError (1121 /* The strong enum '{0}' is not a valid strong dictionary field for the property '{1}.{2}', because its backing type is '{3}'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries. */, property.PropertyType.Name, property.DeclaringType.FullName, property.Name, enumBackingType.FullName));
+ }
+
//
// Processes the various StrongDictionaryAttribute interfaces
//
@@ -1849,41 +1934,32 @@ void GenerateStrongDictionaryTypes ()
string castToUnderlying = "";
string castToEnum = "";
bool isNativeEnum = false;
+ Type? enumBackingType = null;
if (pi.PropertyType.IsEnum) {
- fetchType = pi.PropertyType.GetEnumUnderlyingType ();
- castToUnderlying = "(" + fetchType + "?)";
- castToEnum = "(" + TypeManager.FormatType (dictType, pi.PropertyType) + "?)";
- isNativeEnum = IsNativeEnum (pi.PropertyType);
+ if (IsEnumBackedByNativeType (pi.PropertyType, out enumBackingType)) {
+ ValidateStrongEnumBackingTypeInStrongDictionaryType (pi, enumBackingType);
+ fetchType = enumBackingType;
+ } else {
+ fetchType = pi.PropertyType.GetEnumUnderlyingType ();
+ castToUnderlying = "(" + fetchType + "?)";
+ castToEnum = "(" + TypeManager.FormatType (dictType, pi.PropertyType) + "?)";
+ isNativeEnum = IsNativeEnum (pi.PropertyType);
+ }
}
if (pi.PropertyType.IsValueType) {
- if (pi.PropertyType == TypeCache.System_Boolean) {
- getter = "{1} GetBoolValue ({0})";
- setter = "SetBooleanValue ({0}, {1}value)";
- } else if (fetchType == TypeCache.System_Int32) {
- getter = "{1} GetInt32Value ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (fetchType == TypeCache.System_nint) {
- getter = "{1} GetNIntValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (fetchType == TypeCache.System_Int64) {
- getter = "{1} GetLongValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (fetchType == TypeCache.System_UInt64) {
- getter = "{1} GetULongValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (pi.PropertyType == TypeCache.System_Float) {
- getter = "{1} GetFloatValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (pi.PropertyType == TypeCache.System_Double) {
- getter = "{1} GetDoubleValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (fetchType == TypeCache.System_UInt32) {
- getter = "{1} GetUInt32Value ({0})";
+ if (enumBackingType is not null) {
+ getter = "TryGetNativeValue ({0}, out var handle) ? " + TypeManager.FormatType (null, pi.PropertyType) + "Extensions.GetNullableValue (handle) : null";
+ setter = "SetNativeValue ({0}, value.HasValue ? value.Value.GetConstant () : null)";
+ } else if (isNativeEnum && fetchType == TypeCache.System_Int64) {
+ getter = "{1} (long?) GetNIntValue ({0})";
setter = "SetNumberValue ({0}, {1}value)";
- } else if (fetchType == TypeCache.System_nuint) {
- getter = "{1} GetNUIntValue ({0})";
+ } else if (isNativeEnum && fetchType == TypeCache.System_UInt64) {
+ getter = "{1} (ulong?) GetNUIntValue ({0})";
setter = "SetNumberValue ({0}, {1}value)";
+ } else if (TryGetNSNumberStrongDictionaryMethods (fetchType, out var getNSNumber, out var setNSNumber)) {
+ getter = "{1} " + getNSNumber + " ({0})";
+ setter = setNSNumber + " ({0}, {1}value)";
} else if (fetchType == TypeCache.System_DateTime) {
getter = "GetDateTimeValue ({0})";
setter = "SetNativeValue ({0}, (NSDate?) value)";
@@ -1899,15 +1975,12 @@ void GenerateStrongDictionaryTypes ()
} else if (Frameworks.HaveCoreMedia && fetchType == TypeCache.CMTime) {
getter = "{1} GetCMTimeValue ({0})";
setter = "SetCMTimeValue ({0}, {1}value)";
- } else if (isNativeEnum && fetchType == TypeCache.System_Int64) {
- getter = "{1} (long?) GetNIntValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
- } else if (isNativeEnum && fetchType == TypeCache.System_UInt64) {
- getter = "{1} (ulong?) GetNUIntValue ({0})";
- setter = "SetNumberValue ({0}, {1}value)";
} else if (fetchType == TypeCache.UIEdgeInsets) {
getter = "{1} GetUIEdgeInsets ({0})";
setter = "SetUIEdgeInsets ({0}, {1}value)";
+ } else if (pi.PropertyType.Name == "NMatrix3") {
+ getter = "{1} GetNSDataAsValueType<" + TypeManager.FormatType (null, pi.PropertyType) + "> ({0})";
+ setter = "SetValueTypeAsNSData ({0}, {1}value)";
} else {
exceptions.Add (new BindingException (1033, true, pi.PropertyType, dictType, pi.Name));
continue;
@@ -1915,22 +1988,39 @@ void GenerateStrongDictionaryTypes ()
} else {
if (pi.PropertyType.IsArray) {
var elementType = pi.PropertyType.GetElementType ();
- if (TypeManager.IsWrappedType (elementType)) {
+ if (TypeManager.IsDictionaryContainerType (elementType)) {
+ var dictElementType = TypeManager.FormatType (dictType, elementType);
+ getter = $"GetArrayOfDictionariesValue<{dictElementType}> ({{0}})";
+ setter = "SetArrayOfDictionariesValue ({0}, value)";
+ } else if (TypeCache.INativeObject.IsAssignableFrom (elementType)) {
+ var dictElementType = TypeManager.FormatType (dictType, elementType);
+ getter = "GetArray<" + dictElementType + "> ({0}, (ptr) => Runtime.GetINativeObject<" + dictElementType + "> (ptr, false)!)";
+ setter = "SetArrayValue ({0}, value)";
+ } else if (TypeManager.IsWrappedType (elementType)) {
getter = "GetArray<" + TypeManager.FormatType (dictType, elementType) + "> ({0})";
setter = "SetArrayValue ({0}, value)";
+ } else if (IsEnumBackedByNativeType (elementType, out enumBackingType)) {
+ ValidateStrongEnumBackingTypeInStrongDictionaryType (pi, enumBackingType);
+
+ var enumTypeStr = TypeManager.FormatType (null, elementType);
+ getter = "{1} GetArray<" + enumTypeStr + "> ({0}, (ptr) => ptr == NativeHandle.Zero ? default (" + enumTypeStr + ") : " + enumTypeStr + "Extensions.GetValue (ptr))";
+ setter = "SetArrayValue<" + enumTypeStr + "> ({0}, value, (element) => Runtime.RetainAndAutoreleaseNSObject (element.GetConstant ()))";
} else if (elementType.IsEnum) {
- // Handle arrays of enums as arrays of NSNumbers, casted to the enum
+ var underlyingEnumType = elementType.GetEnumUnderlyingType ();
+ if (!TryGetNSNumberField (underlyingEnumType, out var fieldName))
+ exceptions.Add (ErrorHelper.CreateError (1122 /* Unable to find the corresponding NSNumber property for the type {0} in {1}.{2} */, underlyingEnumType.FullName, pi.DeclaringType.FullName, pi.Name));
+
+ // Handle arrays of enums as arrays of NSNumbers
var enumTypeStr = TypeManager.FormatType (null, elementType);
- getter = "GetArray<" + enumTypeStr +
- "> ({0}, (ptr)=> {{\n\tusing (var num = Runtime.GetNSObject (ptr)!){{\n\t\treturn (" +
- enumTypeStr + ") num.Int32Value;\n\t}}\n}})";
- setter = "SetArrayValue<" + enumTypeStr + "> ({0}, value)";
+ getter = "GetArray<" + enumTypeStr + "> ({0}, (ptr) => (" + enumTypeStr + "?) Runtime.GetNSObjectChecked (ptr)?." + fieldName + " ?? default (" + enumTypeStr + "))";
+ setter = "SetArrayValue<" + enumTypeStr + "> ({0}, value, (element) => Runtime.RetainAndAutoreleaseNSObject (new NSNumber ((" + TypeManager.FormatType (null, underlyingEnumType) + ") element)))";
} else if (elementType == TypeCache.System_String) {
getter = "GetArray ({0}, (ptr) => CFString.FromHandle (ptr)!)";
setter = "SetArrayValue ({0}, value)";
- } else if (elementType.Name == "CTFontDescriptor") {
- getter = "GetArray ({0}, (ptr) => new CTFontDescriptor (ptr, false))";
- setter = "SetArrayValue ({0}, value)";
+ } else if (TryGetNSNumberField (elementType, out var fieldName)) {
+ var renderedElementType = TypeManager.RenderType (elementType);
+ getter = "GetArray<" + renderedElementType + "> ({0}, (ptr) => (" + renderedElementType + "?) Runtime.GetNSObjectChecked (ptr)?." + fieldName + " ?? default (" + renderedElementType + "))";
+ setter = "SetArrayValue<" + renderedElementType + "> ({0}, value)";
} else {
exceptions.Add (new BindingException (1033, true, pi.PropertyType, dictType, pi.Name));
continue;
@@ -1953,7 +2043,7 @@ void GenerateStrongDictionaryTypes ()
} else if (TypeManager.IsDictionaryContainerType (pi.PropertyType) || AttributeManager.HasAttribute (pi)) {
var strType = pi.PropertyType.Name;
getter = $"GetStrongDictionary<{strType}>({{0}}, (dict) => new {strType} (dict))";
- setter = "SetNativeValue ({0}, value.GetDictionary ())";
+ setter = "SetNativeValue ({0}, value?.Dictionary)";
} else if (TypeCache.INativeObject.IsAssignableFrom (pi.PropertyType)) {
getter = $"GetNativeValue<{pi.PropertyType}> ({{0}})";
setter = "SetNativeValue ({0}, value)";
@@ -6151,8 +6241,10 @@ public void Generate (Type type)
if (field_exports.Count != 0) {
foreach (var field_pi in field_exports.OrderBy (f => f.Name, StringComparer.Ordinal)) {
var fieldAttr = AttributeManager.GetCustomAttribute (field_pi);
- if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out string library_name, out string library_path))
- throw ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field_pi.Name);
+ if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out string library_name, out string library_path)) {
+ exceptions.Add (ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field_pi.Name));
+ continue;
+ }
string fieldTypeName;
string smartEnumTypeName = null;
diff --git a/src/coretext.cs b/src/coretext.cs
index f277c80a0585..adaf4be45f19 100644
--- a/src/coretext.cs
+++ b/src/coretext.cs
@@ -15,6 +15,8 @@
namespace CoreText {
+ interface CTFontDescriptor : INativeObject { }
+
[Partial]
interface CTFontManager {
[Field ("kCTFontManagerRegisteredFontsChangedNotification")]
diff --git a/src/corevideo.cs b/src/corevideo.cs
index b83de1ae1698..8e497a400c23 100644
--- a/src/corevideo.cs
+++ b/src/corevideo.cs
@@ -956,6 +956,7 @@ interface CVPixelFormatKeys {
NSString BitsPerComponent { get; }
}
+#if !XAMCORE_5_0
[Partial]
interface CVPixelFormatComponentRangeKeys {
[Field ("kCVPixelFormatComponentRange_VideoRange")]
@@ -980,6 +981,23 @@ interface CVPixelFormatComponentRange {
// there's no documentation about the type, so binding as NSObject
NSObject WideRange { get; set; }
}
+#endif // !XAMCORE_5_0
+
+#if XAMCORE_5_0
+ enum CVPixelFormatComponentRange {
+#else
+ enum CVPixelFormatComponentRangeValues {
+#endif
+ [Field ("kCVPixelFormatComponentRange_VideoRange")]
+ VideoRange,
+
+ [Field ("kCVPixelFormatComponentRange_FullRange")]
+ FullRange,
+
+ [Field ("kCVPixelFormatComponentRange_WideRange")]
+ WideRange,
+ }
+
[StrongDictionary ("CVPixelFormatKeys", Suffix = "")]
interface CVPixelFormatDescription {
@@ -1019,7 +1037,17 @@ interface CVPixelFormatDescription {
bool FormatContainsSenselArray { get; set; }
#endif
+#if XAMCORE_6_0
CVPixelFormatComponentRange ComponentRange { get; set; }
+#elif XAMCORE_5_0
+ CVPixelFormatComponentRange ComponentRange { get; set; }
+ [Export ("ComponentRange")]
+ [Obsolete ("Use 'ComponentRange' instead.")]
+ CVPixelFormatComponentRange ComponentRangeValue { get; set; }
+#else
+ [Export ("ComponentRange")]
+ CVPixelFormatComponentRangeValues ComponentRangeValue { get; set; }
+#endif
// This can be an array of dictionaries, or a single dictionary when there's only one plane, so we have to type as 'NSObject'.
NSObject Planes { get; set; }
diff --git a/tests/bindings-test/ApiDefinition.cs b/tests/bindings-test/ApiDefinition.cs
index df4a237e5d95..8f48ce816216 100644
--- a/tests/bindings-test/ApiDefinition.cs
+++ b/tests/bindings-test/ApiDefinition.cs
@@ -1,5 +1,8 @@
using System;
+using System.Numerics;
+using CoreGraphics;
+using CoreMedia;
using ObjCRuntime;
using Foundation;
#if __MACOS__
@@ -573,4 +576,240 @@ interface VeryGenericFactory {
[Static]
IVeryGenericConsumerProtocol GetConsumer ();
}
+
+ enum StrongEnum {
+ [Field ("StrongEnumA", LibraryName = "__Internal")]
+ A,
+
+ [Field ("StrongEnumB", LibraryName = "__Internal")]
+ B,
+
+ [Field ("StrongEnumC", LibraryName = "__Internal")]
+ C,
+ }
+
+ [Partial]
+ interface StrongDictionaryKeys {
+ // simple types
+ [Field ("StrongDictionarySByteField", LibraryName = "__Internal")]
+ NSString SByteField { get; }
+
+ [Field ("StrongDictionaryInt16Field", LibraryName = "__Internal")]
+ NSString Int16Field { get; }
+
+ [Field ("StrongDictionaryInt32Field", LibraryName = "__Internal")]
+ NSString Int32Field { get; }
+
+ [Field ("StrongDictionaryInt64Field", LibraryName = "__Internal")]
+ NSString Int64Field { get; }
+
+ [Field ("StrongDictionaryByteField", LibraryName = "__Internal")]
+ NSString ByteField { get; }
+
+ [Field ("StrongDictionaryUInt16Field", LibraryName = "__Internal")]
+ NSString UInt16Field { get; }
+
+ [Field ("StrongDictionaryUInt32Field", LibraryName = "__Internal")]
+ NSString UInt32Field { get; }
+
+ [Field ("StrongDictionaryUInt64Field", LibraryName = "__Internal")]
+ NSString UInt64Field { get; }
+
+ [Field ("StrongDictionaryNIntField", LibraryName = "__Internal")]
+ NSString NIntField { get; }
+
+ [Field ("StrongDictionaryNUIntField", LibraryName = "__Internal")]
+ NSString NUIntField { get; }
+
+ [Field ("StrongDictionarySingleField", LibraryName = "__Internal")]
+ NSString SingleField { get; }
+
+ [Field ("StrongDictionaryDoubleField", LibraryName = "__Internal")]
+ NSString DoubleField { get; }
+
+ [Field ("StrongDictionaryNFloatField", LibraryName = "__Internal")]
+ NSString NFloatField { get; }
+
+ [Field ("StrongDictionaryNSObjectField", LibraryName = "__Internal")]
+ NSString NSObjectField { get; }
+
+ [Field ("StrongDictionaryBooleanField", LibraryName = "__Internal")]
+ NSString BooleanField { get; }
+
+ [Field ("StrongDictionaryNSStringField", LibraryName = "__Internal")]
+ NSString NSStringField { get; }
+
+ [Field ("StrongDictionaryNSDateField", LibraryName = "__Internal")]
+ NSString NSDateField { get; }
+
+ [Field ("StrongDictionaryNSDictionaryField", LibraryName = "__Internal")]
+ NSString NSDictionaryField { get; }
+
+ [Field ("StrongDictionaryStrongDictionaryField", LibraryName = "__Internal")]
+ NSString NSStrongDictionaryField { get; }
+
+ [Field ("StrongDictionaryStrongEnumField", LibraryName = "__Internal")]
+ NSString StrongEnumField { get; }
+
+ // arrays of the above
+
+ [Field ("StrongDictionaryArrayOfSByteField", LibraryName = "__Internal")]
+ NSString ArrayOfSByteField { get; }
+
+ [Field ("StrongDictionaryArrayOfInt16Field", LibraryName = "__Internal")]
+ NSString ArrayOfInt16Field { get; }
+
+ [Field ("StrongDictionaryArrayOfInt32Field", LibraryName = "__Internal")]
+ NSString ArrayOfInt32Field { get; }
+
+ [Field ("StrongDictionaryArrayOfInt64Field", LibraryName = "__Internal")]
+ NSString ArrayOfInt64Field { get; }
+
+ [Field ("StrongDictionaryArrayOfByteField", LibraryName = "__Internal")]
+ NSString ArrayOfByteField { get; }
+
+ [Field ("StrongDictionaryArrayOfUInt16Field", LibraryName = "__Internal")]
+ NSString ArrayOfUInt16Field { get; }
+
+ [Field ("StrongDictionaryArrayOfUInt32Field", LibraryName = "__Internal")]
+ NSString ArrayOfUInt32Field { get; }
+
+ [Field ("StrongDictionaryArrayOfUInt64Field", LibraryName = "__Internal")]
+ NSString ArrayOfUInt64Field { get; }
+
+ [Field ("StrongDictionaryArrayOfNIntField", LibraryName = "__Internal")]
+ NSString ArrayOfNIntField { get; }
+
+ [Field ("StrongDictionaryArrayOfNUIntField", LibraryName = "__Internal")]
+ NSString ArrayOfNUIntField { get; }
+
+ [Field ("StrongDictionaryArrayOfSingleField", LibraryName = "__Internal")]
+ NSString ArrayOfSingleField { get; }
+
+ [Field ("StrongDictionaryArrayOfDoubleField", LibraryName = "__Internal")]
+ NSString ArrayOfDoubleField { get; }
+
+ [Field ("StrongDictionaryArrayOfNFloatField", LibraryName = "__Internal")]
+ NSString ArrayOfNFloatField { get; }
+
+ [Field ("StrongDictionaryArrayOfNSObjectField", LibraryName = "__Internal")]
+ NSString ArrayOfNSObjectField { get; }
+
+ [Field ("StrongDictionaryArrayOfBooleanField", LibraryName = "__Internal")]
+ NSString ArrayOfBooleanField { get; }
+
+ [Field ("StrongDictionaryArrayOfNSStringField", LibraryName = "__Internal")]
+ NSString ArrayOfNSStringField { get; }
+
+ [Field ("StrongDictionaryArrayOfNSDateField", LibraryName = "__Internal")]
+ NSString ArrayOfNSDateField { get; }
+
+ [Field ("StrongDictionaryArrayOfNSDictionaryField", LibraryName = "__Internal")]
+ NSString ArrayOfNSDictionaryField { get; }
+
+ [Field ("StrongDictionaryArrayOfStrongDictionaryField", LibraryName = "__Internal")]
+ NSString ArrayOfStrongDictionaryField { get; }
+
+ [Field ("StrongDictionaryArrayOfStrongEnumField", LibraryName = "__Internal")]
+ NSString ArrayOfStrongEnumField { get; }
+
+ // other fields
+
+ [Field ("StrongDictionaryStringField", LibraryName = "__Internal")]
+ NSString StringField { get; }
+
+ [Field ("StrongDictionaryDateTimeField", LibraryName = "__Internal")]
+ NSString DateTimeField { get; }
+
+ [Field ("StrongDictionaryGenericNSDictionaryField", LibraryName = "__Internal")]
+ NSString GenericNSDictionaryField { get; }
+
+ [Field ("StrongDictionaryArrayOfStringField", LibraryName = "__Internal")]
+ NSString ArrayOfStringField { get; }
+
+ [Field ("StrongDictionaryNSDataField", LibraryName = "__Internal")]
+ NSString NSDataField { get; }
+
+ [Field ("StrongDictionaryNSDataAsMatrix3Field", LibraryName = "__Internal")]
+ NSString NSDataAsMatrix3Field { get; }
+
+ [Field ("StrongDictionaryCGRectField", LibraryName = "__Internal")]
+ NSString CGRectField { get; }
+
+ [Field ("StrongDictionaryCGSizeField", LibraryName = "__Internal")]
+ NSString CGSizeField { get; }
+
+ [Field ("StrongDictionaryCGPointField", LibraryName = "__Internal")]
+ NSString CGPointField { get; }
+
+ [Field ("StrongDictionaryCMTimeField", LibraryName = "__Internal")]
+ NSString CMTimeField { get; }
+
+#if !__MACOS__
+ [Field ("StrongDictionaryUIEdgeInsetsField", LibraryName = "__Internal")]
+ NSString UIEdgeInsetsField { get; }
+#endif // !__MACOS__
+ }
+
+ [StrongDictionary ("StrongDictionaryKeys", Suffix = "")]
+ interface WrappedNSDictionary {
+ // simple types
+ sbyte SByteField { get; set; }
+ short Int16Field { get; set; }
+ int Int32Field { get; set; }
+ long Int64Field { get; set; }
+ byte ByteField { get; set; }
+ ushort UInt16Field { get; set; }
+ uint UInt32Field { get; set; }
+ ulong UInt64Field { get; set; }
+ nint NIntField { get; set; }
+ nuint NUIntField { get; set; }
+ float SingleField { get; set; }
+ double DoubleField { get; set; }
+ nfloat NFloatField { get; set; }
+ NSObject NSObjectField { get; set; }
+ bool BooleanField { get; set; }
+ NSString NSStringField { get; set; }
+ NSDate NSDateField { get; set; }
+ NSDictionary NSDictionaryField { get; set; }
+ WrappedNSDictionary NSStrongDictionaryField { get; set; }
+ StrongEnum StrongEnumField { get; set; }
+
+ // arrays of the above
+ sbyte [] ArrayOfSByteField { get; set; }
+ short [] ArrayOfInt16Field { get; set; }
+ int [] ArrayOfInt32Field { get; set; }
+ long [] ArrayOfInt64Field { get; set; }
+ byte [] ArrayOfByteField { get; set; }
+ ushort [] ArrayOfUInt16Field { get; set; }
+ uint [] ArrayOfUInt32Field { get; set; }
+ ulong [] ArrayOfUInt64Field { get; set; }
+ nint [] ArrayOfNIntField { get; set; }
+ nuint [] ArrayOfNUIntField { get; set; }
+ float [] ArrayOfSingleField { get; set; }
+ double [] ArrayOfDoubleField { get; set; }
+ nfloat [] ArrayOfNFloatField { get; set; }
+ NSObject [] ArrayOfNSObjectField { get; set; }
+ bool [] ArrayOfBooleanField { get; set; }
+ NSString [] ArrayOfNSStringField { get; set; }
+ NSDate [] ArrayOfNSDateField { get; set; }
+ NSDictionary [] ArrayOfNSDictionaryField { get; set; }
+ WrappedNSDictionary [] ArrayOfStrongDictionaryField { get; set; }
+ StrongEnum [] ArrayOfStrongEnumField { get; set; }
+
+ // other fields
+ string StringField { get; set; }
+ DateTime DateTimeField { get; set; }
+ NSDictionary GenericNSDictionaryField { get; set; }
+ string [] ArrayOfStringField { get; set; }
+ NSData NSDataField { get; set; }
+ NMatrix3 NSDataAsMatrix3Field { get; set; }
+ CGRect CGRectField { get; set; }
+ CGSize CGSizeField { get; set; }
+ CGPoint CGPointField { get; set; }
+ CMTime CMTimeField { get; set; }
+#if !__MACOS__
+ UIEdgeInsets UIEdgeInsetsField { get; set; }
+#endif // !__MACOS____MACOS__
+ }
}
diff --git a/tests/bindings-test/dotnet/shared.csproj b/tests/bindings-test/dotnet/shared.csproj
index 4a6a2579af4a..a1957248ec75 100644
--- a/tests/bindings-test/dotnet/shared.csproj
+++ b/tests/bindings-test/dotnet/shared.csproj
@@ -6,6 +6,7 @@
..\..\..\..\product.snk
true
true
+ true
$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\..\..'))
$(RootTestsDirectory)\bindings-test
diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt
index 45bfd3766e02..55e90c845e2a 100644
--- a/tests/cecil-tests/Documentation.KnownFailures.txt
+++ b/tests/cecil-tests/Documentation.KnownFailures.txt
@@ -2704,6 +2704,9 @@ F:CoreVideo.CVFillExtendedPixelsCallBackDataStruct.UserInfo
F:CoreVideo.CVFillExtendedPixelsCallBackDataStruct.Version
F:CoreVideo.CVImageBufferAlphaChannelMode.Premultiplied
F:CoreVideo.CVImageBufferAlphaChannelMode.Straight
+F:CoreVideo.CVPixelFormatComponentRangeValues.FullRange
+F:CoreVideo.CVPixelFormatComponentRangeValues.VideoRange
+F:CoreVideo.CVPixelFormatComponentRangeValues.WideRange
F:CoreVideo.CVPixelFormatType.CV16VersatileBayer
F:CoreVideo.CVPixelFormatType.CV422YpCbCr8BiPlanarFullRange
F:CoreVideo.CVPixelFormatType.CV422YpCbCr8BiPlanarVideoRange
@@ -11419,14 +11422,6 @@ M:FileProvider.NSFileProviderUserInfo.#ctor
M:FinderSync.FIFinderSync.GetValuesAsync(System.String[],Foundation.NSUrl)
M:FinderSync.FIFinderSyncProtocol_Extensions.GetValuesAsync(FinderSync.IFIFinderSyncProtocol,System.String[],Foundation.NSUrl)
M:FinderSync.IFIFinderSyncProtocol.GetValuesAsync(System.String[],Foundation.NSUrl)
-M:Foundation.DictionaryContainer.GetArray``1(Foundation.NSString,System.Func{ObjCRuntime.NativeHandle,``0})
-M:Foundation.DictionaryContainer.GetStringArrayValue(Foundation.NSString)
-M:Foundation.DictionaryContainer.GetStrongDictionary``1(Foundation.NSString,System.Func{Foundation.NSDictionary,``0})
-M:Foundation.DictionaryContainer.GetUIEdgeInsets(Foundation.NSString)
-M:Foundation.DictionaryContainer.GetULongValue(Foundation.NSString)
-M:Foundation.DictionaryContainer.SetNumberValue(Foundation.NSString,System.Nullable{System.IntPtr})
-M:Foundation.DictionaryContainer.SetNumberValue(Foundation.NSString,System.Nullable{System.UIntPtr})
-M:Foundation.DictionaryContainer.SetUIEdgeInsets(Foundation.NSString,System.Nullable{UIKit.UIEdgeInsets})
M:Foundation.INSCoding.CreateInstance``1(Foundation.NSCoder)
M:Foundation.INSFilePresenter.AccommodatePresentedItemEviction(System.Action{Foundation.NSError})
M:Foundation.INSItemProviderReading.GetReadableTypeIdentifiers``1
@@ -21007,7 +21002,7 @@ P:CoreVideo.CVPixelFormatDescription.CGBitmapContextCompatibility
P:CoreVideo.CVPixelFormatDescription.CGBitmapInfo
P:CoreVideo.CVPixelFormatDescription.CGImageCompatibility
P:CoreVideo.CVPixelFormatDescription.CodecType
-P:CoreVideo.CVPixelFormatDescription.ComponentRange
+P:CoreVideo.CVPixelFormatDescription.ComponentRangeValue
P:CoreVideo.CVPixelFormatDescription.Constant
P:CoreVideo.CVPixelFormatDescription.ContainsAlpha
P:CoreVideo.CVPixelFormatDescription.ContainsGrayscale
@@ -27161,6 +27156,7 @@ T:CoreVideo.CVOpenGLESTexture
T:CoreVideo.CVOpenGLESTextureCache
T:CoreVideo.CVPixelFormatComponentRange
T:CoreVideo.CVPixelFormatComponentRangeKeys
+T:CoreVideo.CVPixelFormatComponentRangeValues
T:CoreVideo.CVPixelFormatKeys
T:CoreVideo.CVPixelFormatTypeExtensions
T:CoreVideo.CVVersatileBayerPattern
diff --git a/tests/generator/BGenTests.cs b/tests/generator/BGenTests.cs
index 4806d377e1c1..9d94fc34b92a 100644
--- a/tests/generator/BGenTests.cs
+++ b/tests/generator/BGenTests.cs
@@ -1495,6 +1495,7 @@ public void Issue19612 ()
[Test]
[TestCase (Profile.iOS)]
+ [TestCase (Profile.MacCatalyst)]
public void BackingFieldType (Profile profile)
{
Configuration.IgnoreIfIgnoredPlatform (profile.AsPlatform ());
@@ -1511,6 +1512,7 @@ public void BackingFieldType (Profile profile)
new { BackingFieldType = "Int64", NullableType = $"System.Nullable`1", RenderedBackingFieldType = "System.Int64", SimplifiedNullableType = "System.Nullable`1" },
new { BackingFieldType = "UInt32", NullableType = $"System.Nullable`1", RenderedBackingFieldType = "System.UInt32", SimplifiedNullableType = "System.Nullable`1" },
new { BackingFieldType = "UInt64", NullableType = $"System.Nullable`1", RenderedBackingFieldType = "System.UInt64", SimplifiedNullableType = "System.Nullable`1" },
+ new { BackingFieldType = "NSString", NullableType = $"Foundation.NSString", RenderedBackingFieldType = "Foundation.NSString", SimplifiedNullableType = "Foundation.NSString" },
};
foreach (var tc in testCases) {
diff --git a/tests/generator/ErrorTests.cs b/tests/generator/ErrorTests.cs
index 646a57660a4b..ff3cbd912ed4 100644
--- a/tests/generator/ErrorTests.cs
+++ b/tests/generator/ErrorTests.cs
@@ -953,5 +953,41 @@ public void ErrorDomain_NoLibraryName (Profile profile)
bgen.AssertExecuteError ("build");
bgen.AssertError (1087, "Missing value for the 'LibraryName' property for the '[ErrorDomain]' attribute for ErrorDomainNS.EWithDomain (e.g. '[ErrorDomain (\"MyDomain\", LibraryName = \"__Internal\")]')");
}
+
+ [Test]
+ [TestCase (Profile.MacCatalyst)]
+ public void StrongDictionaryErrors (Profile profile)
+ {
+ Configuration.IgnoreIfIgnoredPlatform (profile.AsPlatform ());
+
+ var bgen = new BGenTool ();
+ bgen.Profile = profile;
+ bgen.ProcessEnums = true;
+ bgen.Defines = BGenTool.GetDefaultDefines (profile);
+ bgen.CreateTemporaryBinding (File.ReadAllText (Path.Combine (Configuration.SourceRoot, "tests", "generator", "tests", "strongdictionary-errors.cs")));
+ bgen.AssertExecuteError ("build");
+
+ var errorMessages = new string []
+ {
+ "The strong enum 'NSIntegerFieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.NSIntegerValue', because its backing type is 'System.IntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'NSUIntegerFieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.NSUIntegerValue', because its backing type is 'System.UIntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'Int32FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.Int32Value', because its backing type is 'System.Int32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'Int64FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.Int64Value', because its backing type is 'System.Int64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'UInt32FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.UInt32Value', because its backing type is 'System.UInt32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'UInt64FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.UInt64Value', because its backing type is 'System.UInt64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+
+ "The strong enum 'NSIntegerFieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfNSIntegerValue', because its backing type is 'System.IntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'NSUIntegerFieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfNSUIntegerValue', because its backing type is 'System.UIntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'Int32FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfInt32Value', because its backing type is 'System.Int32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'Int64FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfInt64Value', because its backing type is 'System.Int64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'UInt32FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfUInt32Value', because its backing type is 'System.UInt32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ "The strong enum 'UInt64FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfUInt64Value', because its backing type is 'System.UInt64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.",
+ };
+
+ foreach (var msg in errorMessages)
+ bgen.AssertError (1121, msg);
+
+ bgen.AssertErrorCount (errorMessages.Length);
+ }
}
}
diff --git a/tests/generator/tests/backingfieldtype.cs b/tests/generator/tests/backingfieldtype.cs
index fd360715fc6b..8a602e6e169f 100644
--- a/tests/generator/tests/backingfieldtype.cs
+++ b/tests/generator/tests/backingfieldtype.cs
@@ -44,6 +44,12 @@ enum UInt64FieldType {
G,
}
+ [BackingFieldType (typeof (NSString))]
+ enum NSStringFieldType {
+ [Field ("ZField", "__Internal")]
+ Z,
+ }
+
[BaseType (typeof (NSObject))]
interface SomeObj {
[Export ("nsIntegerField")]
@@ -66,5 +72,8 @@ interface SomeObj {
[Export ("uint64Field")]
UInt64FieldType UInt64Field { get; set; }
+
+ [Export ("nsStringField")]
+ NSStringFieldType NSStringField { get; set; }
}
}
diff --git a/tests/generator/tests/strongdictionary-errors.cs b/tests/generator/tests/strongdictionary-errors.cs
new file mode 100644
index 000000000000..5f37e38dad03
--- /dev/null
+++ b/tests/generator/tests/strongdictionary-errors.cs
@@ -0,0 +1,124 @@
+using System;
+using Foundation;
+
+namespace BackingField {
+ [BackingFieldType (typeof (nint))]
+ enum NSIntegerFieldType {
+ [Field ("AField", "__Internal")]
+ A,
+ }
+
+ [BackingFieldType (typeof (nuint))]
+ enum NSUIntegerFieldType {
+ [Field ("BField", "__Internal")]
+ B,
+ }
+
+ [BackingFieldType (typeof (NSNumber))]
+ enum NSNumberFieldType {
+ [Field ("CField", "__Internal")]
+ C,
+ }
+
+ [BackingFieldType (typeof (Int32))]
+ enum Int32FieldType {
+ [Field ("DField", "__Internal")]
+ D,
+ }
+
+ [BackingFieldType (typeof (Int64))]
+ enum Int64FieldType {
+ [Field ("EField", "__Internal")]
+ E,
+ }
+
+ [BackingFieldType (typeof (UInt32))]
+ enum UInt32FieldType {
+ [Field ("FField", "__Internal")]
+ F,
+ }
+
+ [BackingFieldType (typeof (UInt64))]
+ enum UInt64FieldType {
+ [Field ("GField", "__Internal")]
+ G,
+ }
+
+ [BackingFieldType (typeof (NSString))]
+ enum NSStringFieldType {
+ [Field ("ZField", "__Internal")]
+ Z,
+ }
+
+ [Partial]
+ interface StrongDictionaryKeys {
+ [Field ("StrongDictionaryNSIntegerKey", "__Internal")]
+ NSString NSIntegerValueKey { get; }
+
+ [Field ("StrongDictionaryNSUIntegerKey", "__Internal")]
+ NSString NSUIntegerValueKey { get; }
+
+ [Field ("StrongDictionaryNSNumberKey", "__Internal")]
+ NSString NSNumberValueKey { get; }
+
+ [Field ("StrongDictionaryInt32Key", "__Internal")]
+ NSString Int32ValueKey { get; }
+
+ [Field ("StrongDictionaryInt64Key", "__Internal")]
+ NSString Int64ValueKey { get; }
+
+ [Field ("StrongDictionaryUInt32Key", "__Internal")]
+ NSString UInt32ValueKey { get; }
+
+ [Field ("StrongDictionaryUInt64Key", "__Internal")]
+ NSString UInt64ValueKey { get; }
+
+ [Field ("StrongDictionaryNSStringKey", "__Internal")]
+ NSString NSStringValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfNSIntegerKey", "__Internal")]
+ NSString ArrayOfNSIntegerValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfNSUIntegerKey", "__Internal")]
+ NSString ArrayOfNSUIntegerValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfNSNumberKey", "__Internal")]
+ NSString ArrayOfNSNumberValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfInt32Key", "__Internal")]
+ NSString ArrayOfInt32ValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfInt64Key", "__Internal")]
+ NSString ArrayOfInt64ValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfUInt32Key", "__Internal")]
+ NSString ArrayOfUInt32ValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfUInt64Key", "__Internal")]
+ NSString ArrayOfUInt64ValueKey { get; }
+
+ [Field ("StrongDictionaryArrayOfNSStringKey", "__Internal")]
+ NSString ArrayOfNSStringValueKey { get; }
+ }
+
+ [StrongDictionary ("StrongDictionaryKeys")]
+ interface StrongDictionary {
+ NSIntegerFieldType NSIntegerValue { get; }
+ NSUIntegerFieldType NSUIntegerValue { get; }
+ NSNumberFieldType NSNumberValue { get; }
+ Int32FieldType Int32Value { get; }
+ Int64FieldType Int64Value { get; }
+ UInt32FieldType UInt32Value { get; }
+ UInt64FieldType UInt64Value { get; }
+ NSStringFieldType NSStringValue { get; }
+
+ NSIntegerFieldType [] ArrayOfNSIntegerValue { get; }
+ NSUIntegerFieldType [] ArrayOfNSUIntegerValue { get; }
+ NSNumberFieldType [] ArrayOfNSNumberValue { get; }
+ Int32FieldType [] ArrayOfInt32Value { get; }
+ Int64FieldType [] ArrayOfInt64Value { get; }
+ UInt32FieldType [] ArrayOfUInt32Value { get; }
+ UInt64FieldType [] ArrayOfUInt64Value { get; }
+ NSStringFieldType [] ArrayOfNSStringValue { get; }
+ }
+}
diff --git a/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs b/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs
index 65d4711555c1..84a8827f9b9c 100644
--- a/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs
+++ b/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs
@@ -79,7 +79,8 @@ public void CV32ARGB ()
Assert.AreEqual (false, desc.ContainsGrayscale, "ContainsGrayscale");
if (TestRuntime.CheckXcodeVersion (14, 0))
Assert.IsNull (desc.FormatContainsSenselArray, "FormatContainsSenselArray");
- Assert.IsNull (desc.ComponentRange, "ComponentRange");
+ if (TestRuntime.CheckXcodeVersion (16, 0))
+ Assert.AreEqual (CVPixelFormatComponentRangeValues.FullRange, desc.ComponentRangeValue, "ComponentRangeValue");
Assert.IsNull (desc.Planes, "Planes");
Assert.IsNull (desc.BlockWidth, "BlockWidth");
Assert.IsNull (desc.BlockHeight, "BlockHeight");
diff --git a/tests/monotouch-test/Foundation/DictionaryContainerTest.cs b/tests/monotouch-test/Foundation/DictionaryContainerTest.cs
index cd3fd4cd3f88..914162142e67 100644
--- a/tests/monotouch-test/Foundation/DictionaryContainerTest.cs
+++ b/tests/monotouch-test/Foundation/DictionaryContainerTest.cs
@@ -8,11 +8,21 @@
//
using System;
+using System.Linq;
+
using CoreFoundation;
+using CoreGraphics;
+using CoreMedia;
using Foundation;
using ObjCRuntime;
using NUnit.Framework;
+#if HAS_UIKIT
+using UIKit;
+#endif
+
+using Bindings.Test;
+
namespace MonoTouchFixtures.Foundation {
public class DictionaryContainerPoker : DictionaryContainer {
@@ -233,5 +243,372 @@ public void SetStringValue ()
dc.SetStringValue_ (key, null);
Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0");
}
+
+ [Test]
+ public void WrappedNSDictionary ()
+ {
+ var wrapped = new WrappedNSDictionary ();
+
+ Assert.Multiple (() => {
+ Assert.IsNull (wrapped.SByteField, "SByteField");
+ var valueSByteField = SByte.MaxValue;
+ wrapped.SByteField = valueSByteField;
+ Assert.AreEqual (valueSByteField, wrapped.SByteField, "SByteField - set");
+ wrapped.SByteField = null;
+ Assert.IsNull (wrapped.SByteField, "SByteField - final");
+
+ Assert.IsNull (wrapped.Int16Field, "Int16Field");
+ var valueInt16Field = Int16.MaxValue;
+ wrapped.Int16Field = valueInt16Field;
+ Assert.AreEqual (valueInt16Field, wrapped.Int16Field, "Int16Field - set");
+ wrapped.Int16Field = null;
+ Assert.IsNull (wrapped.Int16Field, "Int16Field - final");
+
+ Assert.IsNull (wrapped.Int32Field, "Int32Field");
+ var valueInt32Field = Int32.MaxValue;
+ wrapped.Int32Field = valueInt32Field;
+ Assert.AreEqual (valueInt32Field, wrapped.Int32Field, "Int32Field - set");
+ wrapped.Int32Field = null;
+ Assert.IsNull (wrapped.Int32Field, "Int32Field - final");
+
+ Assert.IsNull (wrapped.Int64Field, "Int64Field");
+ var valueInt64Field = Int64.MaxValue;
+ wrapped.Int64Field = valueInt64Field;
+ Assert.AreEqual (valueInt64Field, wrapped.Int64Field, "Int64Field - set");
+ wrapped.Int64Field = null;
+ Assert.IsNull (wrapped.Int64Field, "Int64Field - final");
+
+ Assert.IsNull (wrapped.ByteField, "ByteField");
+ var valueByteField = Byte.MaxValue;
+ wrapped.ByteField = valueByteField;
+ Assert.AreEqual (valueByteField, wrapped.ByteField, "ByteField - set");
+ wrapped.ByteField = null;
+ Assert.IsNull (wrapped.ByteField, "ByteField - final");
+
+ Assert.IsNull (wrapped.UInt16Field, "UInt16Field");
+ var valueUInt16Field = UInt16.MaxValue;
+ wrapped.UInt16Field = valueUInt16Field;
+ Assert.AreEqual (valueUInt16Field, wrapped.UInt16Field, "UInt16Field - set");
+ wrapped.UInt16Field = null;
+ Assert.IsNull (wrapped.UInt16Field, "UInt16Field - final");
+
+ Assert.IsNull (wrapped.UInt32Field, "UInt32Field");
+ var valueUInt32Field = UInt32.MaxValue;
+ wrapped.UInt32Field = valueUInt32Field;
+ Assert.AreEqual (valueUInt32Field, wrapped.UInt32Field, "UInt32Field - set");
+ wrapped.UInt32Field = null;
+ Assert.IsNull (wrapped.UInt32Field, "UInt32Field - final");
+
+ Assert.IsNull (wrapped.UInt64Field, "UInt64Field");
+ var valueUInt64Field = UInt64.MaxValue;
+ wrapped.UInt64Field = valueUInt64Field;
+ Assert.AreEqual (valueUInt64Field, wrapped.UInt64Field, "UInt64Field - set");
+ wrapped.UInt64Field = null;
+ Assert.IsNull (wrapped.UInt64Field, "UInt64Field - final");
+
+ Assert.IsNull (wrapped.NIntField, "NIntField");
+ var valueNIntField = nint.MaxValue;
+ wrapped.NIntField = valueNIntField;
+ Assert.AreEqual (valueNIntField, wrapped.NIntField, "NIntField - set");
+ wrapped.NIntField = null;
+ Assert.IsNull (wrapped.NIntField, "NIntField - final");
+
+ Assert.IsNull (wrapped.NUIntField, "NUIntField");
+ var valueNUIntField = nuint.MaxValue;
+ wrapped.NUIntField = valueNUIntField;
+ Assert.AreEqual (valueNUIntField, wrapped.NUIntField, "NUIntField - set");
+ wrapped.NUIntField = null;
+ Assert.IsNull (wrapped.NUIntField, "NUIntField - final");
+
+ Assert.IsNull (wrapped.SingleField, "SingleField");
+ var valueSingleField = Single.MaxValue;
+ wrapped.SingleField = valueSingleField;
+ Assert.AreEqual (valueSingleField, wrapped.SingleField, "SingleField - set");
+ wrapped.SingleField = null;
+ Assert.IsNull (wrapped.SingleField, "SingleField - final");
+
+ Assert.IsNull (wrapped.DoubleField, "DoubleField");
+ var valueDoubleField = Double.MaxValue;
+ wrapped.DoubleField = valueDoubleField;
+ Assert.AreEqual (valueDoubleField, wrapped.DoubleField, "DoubleField - set");
+ wrapped.DoubleField = null;
+ Assert.IsNull (wrapped.DoubleField, "DoubleField - final");
+
+ Assert.IsNull (wrapped.NFloatField, "NFloatField");
+ var valueNFloatField = nfloat.MaxValue;
+ wrapped.NFloatField = valueNFloatField;
+ Assert.AreEqual (valueNFloatField, wrapped.NFloatField, "NFloatField - set");
+ wrapped.NFloatField = null;
+ Assert.IsNull (wrapped.NFloatField, "NFloatField - final");
+
+ Assert.IsNull (wrapped.NSObjectField, "NSObjectField");
+ var valueNSObjectField = (NSString) "NSObjectValue";
+ wrapped.NSObjectField = valueNSObjectField;
+ Assert.AreEqual (valueNSObjectField, wrapped.NSObjectField, "NSObjectField - set");
+ wrapped.NSObjectField = null;
+ Assert.IsNull (wrapped.NSObjectField, "NSObjectField - final");
+
+ Assert.IsNull (wrapped.BooleanField, "BooleanField");
+ var valueBooleanField = true;
+ wrapped.BooleanField = valueBooleanField;
+ Assert.AreEqual (valueBooleanField, wrapped.BooleanField, "BooleanField - set");
+ wrapped.BooleanField = null;
+ Assert.IsNull (wrapped.BooleanField, "BooleanField - final");
+
+ Assert.IsNull (wrapped.NSStringField, "NSStringField");
+ var valueNSStringField = (NSString) "NSStringValue";
+ wrapped.NSStringField = valueNSStringField;
+ Assert.AreEqual (valueNSStringField, wrapped.NSStringField, "NSStringField - set");
+ wrapped.NSStringField = null;
+ Assert.IsNull (wrapped.NSStringField, "NSStringField - final");
+
+ Assert.IsNull (wrapped.NSDateField, "NSDateField");
+ var valueNSDateField = (NSDate) new DateTime (2025, 09, 01, 12, 45, 55, 23).ToUniversalTime ();
+ wrapped.NSDateField = valueNSDateField;
+ Assert.AreEqual (valueNSDateField, wrapped.NSDateField, "NSDateField - set");
+ wrapped.NSDateField = null;
+ Assert.IsNull (wrapped.NSDateField, "NSDateField - final");
+
+ Assert.IsNull (wrapped.NSDictionaryField, "NSDictionaryField");
+ var valueNSDictionaryField = new NSDictionary ();
+ wrapped.NSDictionaryField = valueNSDictionaryField;
+ Assert.AreEqual (valueNSDictionaryField, wrapped.NSDictionaryField, "NSDictionaryField - set");
+ wrapped.NSDictionaryField = null;
+ Assert.IsNull (wrapped.NSDictionaryField, "NSDictionaryField - final");
+
+ Assert.IsNull (wrapped.NSStrongDictionaryField, "NSStrongDictionaryField");
+ var valueNSStrongDictionaryField = new WrappedNSDictionary ();
+ wrapped.NSStrongDictionaryField = valueNSStrongDictionaryField;
+ Assert.AreEqual (valueNSStrongDictionaryField?.Dictionary?.ToString (), wrapped.NSStrongDictionaryField?.Dictionary?.ToString (), "NSStrongDictionaryField - set");
+ wrapped.NSStrongDictionaryField = null;
+ Assert.IsNull (wrapped.NSStrongDictionaryField, "NSStrongDictionaryField - final");
+
+ Assert.IsNull (wrapped.StrongEnumField, "StrongEnumField");
+ var valueStrongEnumField = StrongEnum.C;
+ wrapped.StrongEnumField = valueStrongEnumField;
+ Assert.AreEqual (valueStrongEnumField, wrapped.StrongEnumField, "StrongEnumField - set");
+ wrapped.StrongEnumField = null;
+ Assert.IsNull (wrapped.StrongEnumField, "StrongEnumField - final");
+
+ Assert.IsNull (wrapped.ArrayOfSByteField, "ArrayOfSByteField");
+ var valueArrayOfSByteField = new sbyte [] { 1, 2, 3 };
+ wrapped.ArrayOfSByteField = valueArrayOfSByteField;
+ Assert.AreEqual (valueArrayOfSByteField, wrapped.ArrayOfSByteField, "ArrayOfSByteField - set");
+ wrapped.ArrayOfSByteField = null;
+ Assert.IsNull (wrapped.ArrayOfSByteField, "ArrayOfSByteField - final");
+
+ Assert.IsNull (wrapped.ArrayOfInt16Field, "ArrayOfInt16Field");
+ var valueArrayOfInt16Field = new short [] { 1, 2, 3 };
+ wrapped.ArrayOfInt16Field = valueArrayOfInt16Field;
+ Assert.AreEqual (valueArrayOfInt16Field, wrapped.ArrayOfInt16Field, "ArrayOfInt16Field - set");
+ wrapped.ArrayOfInt16Field = null;
+ Assert.IsNull (wrapped.ArrayOfInt16Field, "ArrayOfInt16Field - final");
+
+ Assert.IsNull (wrapped.ArrayOfInt32Field, "ArrayOfInt32Field");
+ var valueArrayOfInt32Field = new int [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfInt32Field = valueArrayOfInt32Field;
+ Assert.AreEqual (valueArrayOfInt32Field, wrapped.ArrayOfInt32Field, "ArrayOfInt32Field - set");
+ wrapped.ArrayOfInt32Field = null;
+ Assert.IsNull (wrapped.ArrayOfInt32Field, "ArrayOfInt32Field - final");
+
+ Assert.IsNull (wrapped.ArrayOfInt64Field, "ArrayOfInt64Field");
+ var valueArrayOfInt64Field = new long [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfInt64Field = valueArrayOfInt64Field;
+ Assert.AreEqual (valueArrayOfInt64Field, wrapped.ArrayOfInt64Field, "ArrayOfInt64Field - set");
+ wrapped.ArrayOfInt64Field = null;
+ Assert.IsNull (wrapped.ArrayOfInt64Field, "ArrayOfInt64Field - final");
+
+ Assert.IsNull (wrapped.ArrayOfByteField, "ArrayOfByteField");
+ var valueArrayOfByteField = new byte [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfByteField = valueArrayOfByteField;
+ Assert.AreEqual (valueArrayOfByteField, wrapped.ArrayOfByteField, "ArrayOfByteField - set");
+ wrapped.ArrayOfByteField = null;
+ Assert.IsNull (wrapped.ArrayOfByteField, "ArrayOfByteField - final");
+
+ Assert.IsNull (wrapped.ArrayOfUInt16Field, "ArrayOfUInt16Field");
+ var valueArrayOfUInt16Field = new ushort [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfUInt16Field = valueArrayOfUInt16Field;
+ Assert.AreEqual (valueArrayOfUInt16Field, wrapped.ArrayOfUInt16Field, "ArrayOfUInt16Field - set");
+ wrapped.ArrayOfUInt16Field = null;
+ Assert.IsNull (wrapped.ArrayOfUInt16Field, "ArrayOfUInt16Field - final");
+
+ Assert.IsNull (wrapped.ArrayOfUInt32Field, "ArrayOfUInt32Field");
+ var valueArrayOfUInt32Field = new uint [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfUInt32Field = valueArrayOfUInt32Field;
+ Assert.AreEqual (valueArrayOfUInt32Field, wrapped.ArrayOfUInt32Field, "ArrayOfUInt32Field - set");
+ wrapped.ArrayOfUInt32Field = null;
+ Assert.IsNull (wrapped.ArrayOfUInt32Field, "ArrayOfUInt32Field - final");
+
+ Assert.IsNull (wrapped.ArrayOfUInt64Field, "ArrayOfUInt64Field");
+ var valueArrayOfUInt64Field = new ulong [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfUInt64Field = valueArrayOfUInt64Field;
+ Assert.AreEqual (valueArrayOfUInt64Field, wrapped.ArrayOfUInt64Field, "ArrayOfUInt64Field - set");
+ wrapped.ArrayOfUInt64Field = null;
+ Assert.IsNull (wrapped.ArrayOfUInt64Field, "ArrayOfUInt64Field - final");
+
+ Assert.IsNull (wrapped.ArrayOfNIntField, "ArrayOfNIntField");
+ var valueArrayOfNIntField = new nint [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfNIntField = valueArrayOfNIntField;
+ Assert.AreEqual (valueArrayOfNIntField, wrapped.ArrayOfNIntField, "ArrayOfNIntField - set");
+ wrapped.ArrayOfNIntField = null;
+ Assert.IsNull (wrapped.ArrayOfNIntField, "ArrayOfNIntField - final");
+
+ Assert.IsNull (wrapped.ArrayOfNUIntField, "ArrayOfNUIntField");
+ var valueArrayOfNUIntField = new nuint [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfNUIntField = valueArrayOfNUIntField;
+ Assert.AreEqual (valueArrayOfNUIntField, wrapped.ArrayOfNUIntField, "ArrayOfNUIntField - set");
+ wrapped.ArrayOfNUIntField = null;
+ Assert.IsNull (wrapped.ArrayOfNUIntField, "ArrayOfNUIntField - final");
+
+ Assert.IsNull (wrapped.ArrayOfSingleField, "ArrayOfSingleField");
+ var valueArrayOfSingleField = new float [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfSingleField = valueArrayOfSingleField;
+ Assert.AreEqual (valueArrayOfSingleField, wrapped.ArrayOfSingleField, "ArrayOfSingleField - set");
+ wrapped.ArrayOfSingleField = null;
+ Assert.IsNull (wrapped.ArrayOfSingleField, "ArrayOfSingleField - final");
+
+ Assert.IsNull (wrapped.ArrayOfDoubleField, "ArrayOfDoubleField");
+ var valueArrayOfDoubleField = new double [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfDoubleField = valueArrayOfDoubleField;
+ Assert.AreEqual (valueArrayOfDoubleField, wrapped.ArrayOfDoubleField, "ArrayOfDoubleField - set");
+ wrapped.ArrayOfDoubleField = null;
+ Assert.IsNull (wrapped.ArrayOfDoubleField, "ArrayOfDoubleField - final");
+
+ Assert.IsNull (wrapped.ArrayOfNFloatField, "ArrayOfNFloatField");
+ var valueArrayOfNFloatField = new nfloat [] { 1, 2, 3 }; ;
+ wrapped.ArrayOfNFloatField = valueArrayOfNFloatField;
+ Assert.AreEqual (valueArrayOfNFloatField, wrapped.ArrayOfNFloatField, "ArrayOfNFloatField - set");
+ wrapped.ArrayOfNFloatField = null;
+ Assert.IsNull (wrapped.ArrayOfNFloatField, "ArrayOfNFloatField - final");
+
+ Assert.IsNull (wrapped.ArrayOfNSObjectField, "ArrayOfNSObjectField");
+ var valueArrayOfNSObjectField = new NSObject [] { (NSString) "Array1", NSDate.Now };
+ wrapped.ArrayOfNSObjectField = valueArrayOfNSObjectField;
+ Assert.AreEqual (valueArrayOfNSObjectField, wrapped.ArrayOfNSObjectField, "ArrayOfNSObjectField - set");
+ wrapped.ArrayOfNSObjectField = null;
+ Assert.IsNull (wrapped.ArrayOfNSObjectField, "ArrayOfNSObjectField - final");
+
+ Assert.IsNull (wrapped.ArrayOfBooleanField, "ArrayOfBooleanField");
+ var valueArrayOfBooleanField = new bool [] { true, false, true };
+ wrapped.ArrayOfBooleanField = valueArrayOfBooleanField;
+ Assert.AreEqual (valueArrayOfBooleanField, wrapped.ArrayOfBooleanField, "ArrayOfBooleanField - set");
+ wrapped.ArrayOfBooleanField = null;
+ Assert.IsNull (wrapped.ArrayOfBooleanField, "ArrayOfBooleanField - final");
+
+ Assert.IsNull (wrapped.ArrayOfNSStringField, "ArrayOfNSStringField");
+ var valueArrayOfNSStringField = new NSString [] { (NSString) "a", (NSString) "b", (NSString) "c" };
+ wrapped.ArrayOfNSStringField = valueArrayOfNSStringField;
+ Assert.AreEqual (valueArrayOfNSStringField, wrapped.ArrayOfNSStringField, "ArrayOfNSStringField - set");
+ wrapped.ArrayOfNSStringField = null;
+ Assert.IsNull (wrapped.ArrayOfNSStringField, "ArrayOfNSStringField - final");
+
+ Assert.IsNull (wrapped.ArrayOfNSDateField, "ArrayOfNSDateField");
+ var valueArrayOfNSDateField = new NSDate [] { NSDate.Now, NSDate.Now };
+ wrapped.ArrayOfNSDateField = valueArrayOfNSDateField;
+ Assert.AreEqual (valueArrayOfNSDateField, wrapped.ArrayOfNSDateField, "ArrayOfNSDateField - set");
+ wrapped.ArrayOfNSDateField = null;
+ Assert.IsNull (wrapped.ArrayOfNSDateField, "ArrayOfNSDateField - final");
+
+ Assert.IsNull (wrapped.ArrayOfNSDictionaryField, "ArrayOfNSDictionaryField");
+ var valueArrayOfNSDictionaryField = new NSDictionary [] { new NSDictionary (), new NSDictionary () };
+ wrapped.ArrayOfNSDictionaryField = valueArrayOfNSDictionaryField;
+ Assert.AreEqual (valueArrayOfNSDictionaryField, wrapped.ArrayOfNSDictionaryField, "ArrayOfNSDictionaryField - set");
+ wrapped.ArrayOfNSDictionaryField = null;
+ Assert.IsNull (wrapped.ArrayOfNSDictionaryField, "ArrayOfNSDictionaryField - final");
+
+ Assert.IsNull (wrapped.ArrayOfStrongDictionaryField, "ArrayOfStrongDictionaryField");
+ var valueArrayOfStrongDictionaryField = new WrappedNSDictionary [] { new WrappedNSDictionary (), new WrappedNSDictionary () };
+ wrapped.ArrayOfStrongDictionaryField = valueArrayOfStrongDictionaryField;
+ Assert.AreEqual (string.Join (";", valueArrayOfStrongDictionaryField.Select (v => v?.Dictionary?.ToString ())), string.Join (";", wrapped.ArrayOfStrongDictionaryField.Select (v => v?.Dictionary?.ToString ())), "ArrayOfStrongDictionaryField - set");
+ wrapped.ArrayOfStrongDictionaryField = null;
+ Assert.IsNull (wrapped.ArrayOfStrongDictionaryField, "ArrayOfStrongDictionaryField - final");
+
+ Assert.IsNull (wrapped.ArrayOfStrongEnumField, "ArrayOfStrongEnumField");
+ var valueArrayOfStrongEnumField = new StrongEnum [] { StrongEnum.A, StrongEnum.B };
+ wrapped.ArrayOfStrongEnumField = valueArrayOfStrongEnumField;
+ Assert.AreEqual (valueArrayOfStrongEnumField, wrapped.ArrayOfStrongEnumField, "ArrayOfStrongEnumField - set");
+ wrapped.ArrayOfStrongEnumField = null;
+ Assert.IsNull (wrapped.ArrayOfStrongEnumField, "ArrayOfStrongEnumField - final");
+
+ Assert.IsNull (wrapped.StringField, "StringField");
+ var valueStringField = "managed string";
+ wrapped.StringField = valueStringField;
+ Assert.AreEqual (valueStringField, wrapped.StringField, "StringField - set");
+ wrapped.StringField = null;
+ Assert.IsNull (wrapped.StringField, "StringField - final");
+
+ Assert.IsNull (wrapped.DateTimeField, "DateTimeField");
+ var valueDateTimeField = new DateTime (2025, 09, 01, 12, 45, 55, 23).ToUniversalTime ();
+ wrapped.DateTimeField = valueDateTimeField;
+ Assert.AreEqual (valueDateTimeField, wrapped.DateTimeField, "DateTimeField - set");
+ wrapped.DateTimeField = null;
+ Assert.IsNull (wrapped.DateTimeField, "DateTimeField - final");
+
+ Assert.IsNull (wrapped.GenericNSDictionaryField, "GenericNSDictionaryField");
+ var valueGenericNSDictionaryField = new NSDictionary ();
+ wrapped.GenericNSDictionaryField = valueGenericNSDictionaryField;
+ Assert.AreEqual (valueGenericNSDictionaryField, wrapped.GenericNSDictionaryField, "GenericNSDictionaryField - set");
+ wrapped.GenericNSDictionaryField = null;
+ Assert.IsNull (wrapped.GenericNSDictionaryField, "GenericNSDictionaryField - final");
+
+ Assert.IsNull (wrapped.ArrayOfStringField, "ArrayOfStringField");
+ var valueArrayOfStringField = new string [] { "abc", "def", "ghi" };
+ wrapped.ArrayOfStringField = valueArrayOfStringField;
+ Assert.AreEqual (valueArrayOfStringField, wrapped.ArrayOfStringField, "ArrayOfStringField - set");
+ wrapped.ArrayOfStringField = null;
+ Assert.IsNull (wrapped.ArrayOfStringField, "ArrayOfStringField - final");
+
+ Assert.IsNull (wrapped.NSDataField, "NSDataField");
+ var valueNSDataField = NSData.FromArray (new byte [] { 1, 2, 3 });
+ wrapped.NSDataField = valueNSDataField;
+ Assert.AreEqual (valueNSDataField, wrapped.NSDataField, "NSDataField - set");
+ wrapped.NSDataField = null;
+ Assert.IsNull (wrapped.NSDataField, "NSDataField - final");
+
+ Assert.IsNull (wrapped.NSDataAsMatrix3Field, "NSDataAsMatrix3Field");
+ var valueNSDataAsMatrix3Field = new NMatrix3 (1, 2, 3, 4, 5, 6, 7, 8, 9);
+ wrapped.NSDataAsMatrix3Field = valueNSDataAsMatrix3Field;
+ Assert.AreEqual (valueNSDataAsMatrix3Field, wrapped.NSDataAsMatrix3Field, "NSDataAsMatrix3Field - set");
+ wrapped.NSDataAsMatrix3Field = null;
+ Assert.IsNull (wrapped.NSDataAsMatrix3Field, "NSDataAsMatrix3Field - final");
+
+ Assert.IsNull (wrapped.CGRectField, "CGRectField");
+ var valueCGRectField = new CGRect (1, 2, 3, 4);
+ wrapped.CGRectField = valueCGRectField;
+ Assert.AreEqual (valueCGRectField, wrapped.CGRectField, "CGRectField - set");
+ wrapped.CGRectField = null;
+ Assert.IsNull (wrapped.CGRectField, "CGRectField - final");
+
+ Assert.IsNull (wrapped.CGSizeField, "CGSizeField");
+ var valueCGSizeField = new CGSize (5, 6);
+ wrapped.CGSizeField = valueCGSizeField;
+ Assert.AreEqual (valueCGSizeField, wrapped.CGSizeField, "CGSizeField - set");
+ wrapped.CGSizeField = null;
+ Assert.IsNull (wrapped.CGSizeField, "CGSizeField - final");
+
+ Assert.IsNull (wrapped.CGPointField, "CGPointField");
+ var valueCGPointField = new CGPoint (7, 8);
+ wrapped.CGPointField = valueCGPointField;
+ Assert.AreEqual (valueCGPointField, wrapped.CGPointField, "CGPointField - set");
+ wrapped.CGPointField = null;
+ Assert.IsNull (wrapped.CGPointField, "CGPointField - final");
+
+ Assert.IsNull (wrapped.CMTimeField, "CMTimeField");
+ var valueCMTimeField = new CMTime (123, 2);
+ wrapped.CMTimeField = valueCMTimeField;
+ Assert.AreEqual (valueCMTimeField, wrapped.CMTimeField, "CMTimeField - set");
+ wrapped.CMTimeField = null;
+ Assert.IsNull (wrapped.CMTimeField, "CMTimeField - final");
+
+#if HAS_UIKIT
+ Assert.IsNull (wrapped.UIEdgeInsetsField, "UIEdgeInsetsField");
+ var valueUIEdgeInsetsField = new UIEdgeInsets (9, 8, 7, 6);
+ wrapped.UIEdgeInsetsField = valueUIEdgeInsetsField;
+ Assert.AreEqual (valueUIEdgeInsetsField, wrapped.UIEdgeInsetsField, "UIEdgeInsetsField - set");
+ wrapped.UIEdgeInsetsField = null;
+ Assert.IsNull (wrapped.UIEdgeInsetsField, "UIEdgeInsetsField - final");
+#endif // HAS_UIKIT
+ });
+ }
}
}
diff --git a/tests/test-libraries/libtest.m b/tests/test-libraries/libtest.m
index 6da86024410f..d83a53f1b7b6 100644
--- a/tests/test-libraries/libtest.m
+++ b/tests/test-libraries/libtest.m
@@ -9,6 +9,68 @@
NSString *x_GlobalString = @"There's nothing cruvus here!";
+// Strong enum
+NSString *StrongEnumA = @"A";
+NSString *StrongEnumB = @"B";
+NSString *StrongEnumC = @"C";
+
+// Strong dictionary keys
+
+// simple types
+NSString *StrongDictionarySByteField = @"StrongDictionarySByteField";
+NSString *StrongDictionaryInt16Field = @"StrongDictionaryInt16Field";
+NSString *StrongDictionaryInt32Field = @"StrongDictionaryInt32Field";
+NSString *StrongDictionaryInt64Field = @"StrongDictionaryInt64Field";
+NSString *StrongDictionaryByteField = @"StrongDictionaryByteField";
+NSString *StrongDictionaryUInt16Field = @"StrongDictionaryUInt16Field";
+NSString *StrongDictionaryUInt32Field = @"StrongDictionaryUInt32Field";
+NSString *StrongDictionaryUInt64Field = @"StrongDictionaryUInt64Field";
+NSString *StrongDictionaryNIntField = @"StrongDictionaryNIntField";
+NSString *StrongDictionaryNUIntField = @"StrongDictionaryNUIntField";
+NSString *StrongDictionarySingleField = @"StrongDictionarySingleField";
+NSString *StrongDictionaryDoubleField = @"StrongDictionaryDoubleField";
+NSString *StrongDictionaryNFloatField = @"StrongDictionaryNFloatField";
+NSString *StrongDictionaryNSObjectField = @"StrongDictionaryNSObjectField";
+NSString *StrongDictionaryBooleanField = @"StrongDictionaryBooleanField";
+NSString *StrongDictionaryNSStringField = @"StrongDictionaryNSStringField";
+NSString *StrongDictionaryNSDateField = @"StrongDictionaryNSDateField";
+NSString *StrongDictionaryNSDictionaryField = @"StrongDictionaryNSDictionaryField";
+NSString *StrongDictionaryStrongDictionaryField = @"StrongDictionaryStrongDictionaryField";
+NSString *StrongDictionaryStrongEnumField = @"StrongDictionaryStrongEnumField";
+// arrays of the above
+NSString *StrongDictionaryArrayOfSByteField = @"StrongDictionaryArrayOfSByteField";
+NSString *StrongDictionaryArrayOfInt16Field = @"StrongDictionaryArrayOfInt16Field";
+NSString *StrongDictionaryArrayOfInt32Field = @"StrongDictionaryArrayOfInt32Field";
+NSString *StrongDictionaryArrayOfInt64Field = @"StrongDictionaryArrayOfInt64Field";
+NSString *StrongDictionaryArrayOfByteField = @"StrongDictionaryArrayOfByteField";
+NSString *StrongDictionaryArrayOfUInt16Field = @"StrongDictionaryArrayOfUInt16Field";
+NSString *StrongDictionaryArrayOfUInt32Field = @"StrongDictionaryArrayOfUInt32Field";
+NSString *StrongDictionaryArrayOfUInt64Field = @"StrongDictionaryArrayOfUInt64Field";
+NSString *StrongDictionaryArrayOfNIntField = @"StrongDictionaryArrayOfNIntField";
+NSString *StrongDictionaryArrayOfNUIntField = @"StrongDictionaryArrayOfNUIntField";
+NSString *StrongDictionaryArrayOfSingleField = @"StrongDictionaryArrayOfSingleField";
+NSString *StrongDictionaryArrayOfDoubleField = @"StrongDictionaryArrayOfDoubleField";
+NSString *StrongDictionaryArrayOfNFloatField = @"StrongDictionaryArrayOfNFloatField";
+NSString *StrongDictionaryArrayOfNSObjectField = @"StrongDictionaryArrayOfNSObjectField";
+NSString *StrongDictionaryArrayOfBooleanField = @"StrongDictionaryArrayOfBooleanField";
+NSString *StrongDictionaryArrayOfNSStringField = @"StrongDictionaryArrayOfNSStringField";
+NSString *StrongDictionaryArrayOfNSDateField = @"StrongDictionaryArrayOfNSDateField";
+NSString *StrongDictionaryArrayOfNSDictionaryField = @"StrongDictionaryArrayOfNSDictionaryField";
+NSString *StrongDictionaryArrayOfStrongDictionaryField = @"StrongDictionaryArrayOfStrongDictionaryField";
+NSString *StrongDictionaryArrayOfStrongEnumField = @"StrongDictionaryArrayOfStrongEnumField";
+// other fields
+NSString *StrongDictionaryStringField = @"StrongDictionaryStringField";
+NSString *StrongDictionaryDateTimeField = @"StrongDictionaryDateTimeField";
+NSString *StrongDictionaryGenericNSDictionaryField = @"StrongDictionaryGenericNSDictionaryField";
+NSString *StrongDictionaryArrayOfStringField = @"StrongDictionaryArrayOfStringField";
+NSString *StrongDictionaryNSDataField = @"StrongDictionaryNSDataField";
+NSString *StrongDictionaryNSDataAsMatrix3Field = @"StrongDictionaryNSDataAsMatrix3Field";
+NSString *StrongDictionaryCGRectField = @"StrongDictionaryCGRectField";
+NSString *StrongDictionaryCGSizeField = @"StrongDictionaryCGSizeField";
+NSString *StrongDictionaryCGPointField = @"StrongDictionaryCGPointField";
+NSString *StrongDictionaryCMTimeField = @"StrongDictionaryCMTimeField";
+NSString *StrongDictionaryUIEdgeInsetsField = @"StrongDictionaryUIEdgeInsetsField";
+
int
theUltimateAnswer ()
{
diff --git a/tests/test-libraries/rename.h b/tests/test-libraries/rename.h
index 6b35363e9ce9..8bd7e9de3442 100644
--- a/tests/test-libraries/rename.h
+++ b/tests/test-libraries/rename.h
@@ -75,6 +75,55 @@
#define x_SCNMatrix4Translate object_x_SCNMatrix4Translate
#define x_GlobalString object_x_GlobalString
#define x_native_field object_x_native_field
+ #define StrongDictionarySByteField object_StrongDictionarySByteField
+ #define StrongDictionaryInt16Field object_StrongDictionaryInt16Field
+ #define StrongDictionaryInt32Field object_StrongDictionaryInt32Field
+ #define StrongDictionaryInt64Field object_StrongDictionaryInt64Field
+ #define StrongDictionaryByteField object_StrongDictionaryByteField
+ #define StrongDictionaryUInt16Field object_StrongDictionaryUInt16Field
+ #define StrongDictionaryUInt32Field object_StrongDictionaryUInt32Field
+ #define StrongDictionaryUInt64Field object_StrongDictionaryUInt64Field
+ #define StrongDictionaryNIntField object_StrongDictionaryNIntField
+ #define StrongDictionaryNUIntField object_StrongDictionaryNUIntField
+ #define StrongDictionarySingleField object_StrongDictionarySingleField
+ #define StrongDictionaryDoubleField object_StrongDictionaryDoubleField
+ #define StrongDictionaryNFloatField object_StrongDictionaryNFloatField
+ #define StrongDictionaryNSObjectField object_StrongDictionaryNSObjectField
+ #define StrongDictionaryBooleanField object_StrongDictionaryBooleanField
+ #define StrongDictionaryNSStringField object_StrongDictionaryNSStringField
+ #define StrongDictionaryNSDateField object_StrongDictionaryNSDateField
+ #define StrongDictionaryNSDictionaryField object_StrongDictionaryNSDictionaryField
+ #define StrongDictionaryStrongDictionaryField object_StrongDictionaryStrongDictionaryField
+ #define StrongDictionaryArrayOfSByteField object_StrongDictionaryArrayOfSByteField
+ #define StrongDictionaryArrayOfInt16Field object_StrongDictionaryArrayOfInt16Field
+ #define StrongDictionaryArrayOfInt32Field object_StrongDictionaryArrayOfInt32Field
+ #define StrongDictionaryArrayOfInt64Field object_StrongDictionaryArrayOfInt64Field
+ #define StrongDictionaryArrayOfByteField object_StrongDictionaryArrayOfByteField
+ #define StrongDictionaryArrayOfUInt16Field object_StrongDictionaryArrayOfUInt16Field
+ #define StrongDictionaryArrayOfUInt32Field object_StrongDictionaryArrayOfUInt32Field
+ #define StrongDictionaryArrayOfUInt64Field object_StrongDictionaryArrayOfUInt64Field
+ #define StrongDictionaryArrayOfNIntField object_StrongDictionaryArrayOfNIntField
+ #define StrongDictionaryArrayOfNUIntField object_StrongDictionaryArrayOfNUIntField
+ #define StrongDictionaryArrayOfSingleField object_StrongDictionaryArrayOfSingleField
+ #define StrongDictionaryArrayOfDoubleField object_StrongDictionaryArrayOfDoubleField
+ #define StrongDictionaryArrayOfNFloatField object_StrongDictionaryArrayOfNFloatField
+ #define StrongDictionaryArrayOfNSObjectField object_StrongDictionaryArrayOfNSObjectField
+ #define StrongDictionaryArrayOfBooleanField object_StrongDictionaryArrayOfBooleanField
+ #define StrongDictionaryArrayOfNSStringField object_StrongDictionaryArrayOfNSStringField
+ #define StrongDictionaryArrayOfNSDateField object_StrongDictionaryArrayOfNSDateField
+ #define StrongDictionaryArrayOfNSDictionaryField object_StrongDictionaryArrayOfNSDictionaryField
+ #define StrongDictionaryArrayOfStrongDictionaryField object_StrongDictionaryArrayOfStrongDictionaryField
+ #define StrongDictionaryStringField object_StrongDictionaryStringField
+ #define StrongDictionaryDateField object_StrongDictionaryDateField
+ #define StrongDictionaryGenericNSDictionaryField object_StrongDictionaryGenericNSDictionaryField
+ #define StrongDictionaryArrayOfStringField object_StrongDictionaryArrayOfStringField
+ #define StrongDictionaryNSDataField object_StrongDictionaryNSDataField
+ #define StrongDictionaryNSDataAsMatrix3Field object_StrongDictionaryNSDataAsMatrix3Field
+ #define StrongDictionaryCGRectField object_StrongDictionaryCGRectField
+ #define StrongDictionaryCGSizeField object_StrongDictionaryCGSizeField
+ #define StrongDictionaryCGPointField object_StrongDictionaryCGPointField
+ #define StrongDictionaryCMTimeField object_StrongDictionaryCMTimeField
+ #define StrongDictionaryUIEdgeInsetsField object_StrongDictionaryUIEdgeInsetsField
#elif PREFIX == 2
#define theUltimateAnswer ar_theUltimateAnswer
#define useZLib ar_useZLib
@@ -151,6 +200,55 @@
#define x_SCNMatrix4Translate ar_x_SCNMatrix4Translate
#define x_GlobalString ar_x_GlobalString
#define x_native_field ar_x_native_field
+ #define StrongDictionarySByteField ar_StrongDictionarySByteField
+ #define StrongDictionaryInt16Field ar_StrongDictionaryInt16Field
+ #define StrongDictionaryInt32Field ar_StrongDictionaryInt32Field
+ #define StrongDictionaryInt64Field ar_StrongDictionaryInt64Field
+ #define StrongDictionaryByteField ar_StrongDictionaryByteField
+ #define StrongDictionaryUInt16Field ar_StrongDictionaryUInt16Field
+ #define StrongDictionaryUInt32Field ar_StrongDictionaryUInt32Field
+ #define StrongDictionaryUInt64Field ar_StrongDictionaryUInt64Field
+ #define StrongDictionaryNIntField ar_StrongDictionaryNIntField
+ #define StrongDictionaryNUIntField ar_StrongDictionaryNUIntField
+ #define StrongDictionarySingleField ar_StrongDictionarySingleField
+ #define StrongDictionaryDoubleField ar_StrongDictionaryDoubleField
+ #define StrongDictionaryNFloatField ar_StrongDictionaryNFloatField
+ #define StrongDictionaryNSObjectField ar_StrongDictionaryNSObjectField
+ #define StrongDictionaryBooleanField ar_StrongDictionaryBooleanField
+ #define StrongDictionaryNSStringField ar_StrongDictionaryNSStringField
+ #define StrongDictionaryNSDateField ar_StrongDictionaryNSDateField
+ #define StrongDictionaryNSDictionaryField ar_StrongDictionaryNSDictionaryField
+ #define StrongDictionaryStrongDictionaryField ar_StrongDictionaryStrongDictionaryField
+ #define StrongDictionaryArrayOfSByteField ar_StrongDictionaryArrayOfSByteField
+ #define StrongDictionaryArrayOfInt16Field ar_StrongDictionaryArrayOfInt16Field
+ #define StrongDictionaryArrayOfInt32Field ar_StrongDictionaryArrayOfInt32Field
+ #define StrongDictionaryArrayOfInt64Field ar_StrongDictionaryArrayOfInt64Field
+ #define StrongDictionaryArrayOfByteField ar_StrongDictionaryArrayOfByteField
+ #define StrongDictionaryArrayOfUInt16Field ar_StrongDictionaryArrayOfUInt16Field
+ #define StrongDictionaryArrayOfUInt32Field ar_StrongDictionaryArrayOfUInt32Field
+ #define StrongDictionaryArrayOfUInt64Field ar_StrongDictionaryArrayOfUInt64Field
+ #define StrongDictionaryArrayOfNIntField ar_StrongDictionaryArrayOfNIntField
+ #define StrongDictionaryArrayOfNUIntField ar_StrongDictionaryArrayOfNUIntField
+ #define StrongDictionaryArrayOfSingleField ar_StrongDictionaryArrayOfSingleField
+ #define StrongDictionaryArrayOfDoubleField ar_StrongDictionaryArrayOfDoubleField
+ #define StrongDictionaryArrayOfNFloatField ar_StrongDictionaryArrayOfNFloatField
+ #define StrongDictionaryArrayOfNSObjectField ar_StrongDictionaryArrayOfNSObjectField
+ #define StrongDictionaryArrayOfBooleanField ar_StrongDictionaryArrayOfBooleanField
+ #define StrongDictionaryArrayOfNSStringField ar_StrongDictionaryArrayOfNSStringField
+ #define StrongDictionaryArrayOfNSDateField ar_StrongDictionaryArrayOfNSDateField
+ #define StrongDictionaryArrayOfNSDictionaryField ar_StrongDictionaryArrayOfNSDictionaryField
+ #define StrongDictionaryArrayOfStrongDictionaryField ar_StrongDictionaryArrayOfStrongDictionaryField
+ #define StrongDictionaryStringField ar_StrongDictionaryStringField
+ #define StrongDictionaryDateField ar_StrongDictionaryDateField
+ #define StrongDictionaryGenericNSDictionaryField ar_StrongDictionaryGenericNSDictionaryField
+ #define StrongDictionaryArrayOfStringField ar_StrongDictionaryArrayOfStringField
+ #define StrongDictionaryNSDataField ar_StrongDictionaryNSDataField
+ #define StrongDictionaryNSDataAsMatrix3Field ar_StrongDictionaryNSDataAsMatrix3Field
+ #define StrongDictionaryCGRectField ar_StrongDictionaryCGRectField
+ #define StrongDictionaryCGSizeField ar_StrongDictionaryCGSizeField
+ #define StrongDictionaryCGPointField ar_StrongDictionaryCGPointField
+ #define StrongDictionaryCMTimeField ar_StrongDictionaryCMTimeField
+ #define StrongDictionaryUIEdgeInsetsField ar_StrongDictionaryUIEdgeInsetsField
#else
// keep original names
#endif
diff --git a/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore b/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore
index 63cf707b6bc0..516a8af5896b 100644
--- a/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore
+++ b/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore
@@ -516,7 +516,6 @@
!missing-pinvoke! CFDictionaryCreateMutableCopy is not bound
!missing-pinvoke! CFDictionaryGetCountOfKey is not bound
!missing-pinvoke! CFDictionaryGetCountOfValue is not bound
-!missing-pinvoke! CFDictionaryGetValueIfPresent is not bound
!missing-pinvoke! CFDictionaryRemoveAllValues is not bound
!missing-pinvoke! CFDictionaryRemoveValue is not bound
!missing-pinvoke! CFDictionaryReplaceValue is not bound
diff --git a/tools/devops/automation/templates/tests-stage.yml b/tools/devops/automation/templates/tests-stage.yml
index fb26d9dd79e6..1e332637a330 100644
--- a/tools/devops/automation/templates/tests-stage.yml
+++ b/tools/devops/automation/templates/tests-stage.yml
@@ -64,7 +64,7 @@ parameters:
{
stageName: 'mac_14_x64',
displayName: 'X64 - Mac Sonoma (14)',
- macPool: 'VSEng-Xamarin-RedmondMacBuildPool-iOS-Untrusted',
+ macPool: 'VSEng-VSMac-Xamarin-Shared',
useImage: false,
statusContext: 'X64 - Mac Sonoma (14)',
demands: [