[UIKit] Fix broken UITrait bindings. Fixes #19410. (#19411)

There are a few issues with the bindings, because the typedef `UITrait`
in the headers is defined like this:

```objective-c
typedef Class<UITraitDefinition> UITrait
```

which means: "A Class that implements the UITraitDefinition protocol",
and not "The UITraitDefinition" protocol", which is how it was bound.

This means the corresponding bindings are incorrect, so fix them. In
some cases it's not possible to fix the API, so new ones had to be
implemented in order to maintain backwards compatibility.

Fixes https://github.com/xamarin/xamarin-macios/issues/19410.
This commit is contained in:
Rolf Bjarne Kvinge 2024-01-03 09:03:08 +01:00 коммит произвёл GitHub
Родитель f39489fe60
Коммит b3e5784ef6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 692 добавлений и 6 удалений

Просмотреть файл

@ -0,0 +1,311 @@
//
// UITraitChangeObservable.cs: support for IUITraitChangeObservable
//
// Authors:
// Rolf Bjarne Kvinge
//
// Copyright 2023 Microsoft Corp. All rights reserved.
//
#if !__WATCHOS__
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Foundation;
using ObjCRuntime;
#if !NET
using NativeHandle = System.IntPtr;
#endif
#nullable enable
namespace UIKit {
public partial interface IUITraitChangeObservable {
static Class [] ToClasses (params Type [] traits)
{
if (traits is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (traits));
var traitsClasses = new Class [traits.Length];
for (var i = 0; i < traits.Length; i++)
traitsClasses [i] = new Class (traits [i]);
return traitsClasses;
}
/// <summary>
/// Registers a callback handler that will be executed when one of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public IUITraitChangeRegistration RegisterForTraitChanges (Type [] traits, Action<IUITraitEnvironment, UITraitCollection> handler)
{
return RegisterForTraitChanges (ToClasses (traits), handler);
}
/// <summary>
/// Registers a callback handler that will be executed when one of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public unsafe IUITraitChangeRegistration RegisterForTraitChanges (Action<IUITraitEnvironment, UITraitCollection> handler, params Type [] traits)
{
// Add an override with 'params', unfortunately this means reordering the parameters.
return RegisterForTraitChanges (ToClasses (traits), handler);
}
/// <summary>
/// Registers a callback handler that will be executed when the specified trait changes.
/// </summary>
/// <typeparam name="T">The trait to observe.</typeparam>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public unsafe IUITraitChangeRegistration RegisterForTraitChanges<T> (Action<IUITraitEnvironment, UITraitCollection> handler)
where T : IUITraitDefinition
{
return RegisterForTraitChanges (ToClasses (typeof (T)), handler);
}
/// <summary>
/// Registers a callback handler that will be executed when any of the specified traits changes.
/// </summary>
/// <typeparam name="T1">A trait to observe</typeparam>
/// <typeparam name="T2">A trait to observe</typeparam>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public unsafe IUITraitChangeRegistration RegisterForTraitChanges<T1, T2> (Action<IUITraitEnvironment, UITraitCollection> handler)
where T1 : IUITraitDefinition
where T2 : IUITraitDefinition
{
return RegisterForTraitChanges (ToClasses (typeof (T1), typeof (T2)), handler);
}
/// <summary>
/// Registers a callback handler that will be executed when any of the specified traits changes.
/// </summary>
/// <typeparam name="T1">A trait to observe</typeparam>
/// <typeparam name="T2">A trait to observe</typeparam>
/// <typeparam name="T3">A trait to observe</typeparam>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public unsafe IUITraitChangeRegistration RegisterForTraitChanges<T1, T2, T3> (Action<IUITraitEnvironment, UITraitCollection> handler)
where T1 : IUITraitDefinition
where T2 : IUITraitDefinition
where T3 : IUITraitDefinition
{
return RegisterForTraitChanges (ToClasses (typeof (T1), typeof (T2), typeof (T3)), handler);
}
/// <summary>
/// Registers a callback handler that will be executed when any of the specified traits changes.
/// </summary>
/// <typeparam name="T1">A trait to observe</typeparam>
/// <typeparam name="T2">A trait to observe</typeparam>
/// <typeparam name="T3">A trait to observe</typeparam>
/// <typeparam name="T4">A trait to observe</typeparam>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public unsafe IUITraitChangeRegistration RegisterForTraitChanges<T1, T2, T3, T4> (Action<IUITraitEnvironment, UITraitCollection> handler)
where T1 : IUITraitDefinition
where T2 : IUITraitDefinition
where T3 : IUITraitDefinition
where T4 : IUITraitDefinition
{
return RegisterForTraitChanges (ToClasses (typeof (T1), typeof (T2), typeof (T3), typeof (T4)), handler);
}
/// <summary>
/// Registers a selector that will be called on the specified object when any of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="target">The object whose specified selector will be called.</param>
/// <param name="action">The selector to call on the specified object.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public IUITraitChangeRegistration RegisterForTraitChanges (Type [] traits, NSObject target, Selector action)
{
return RegisterForTraitChanges (ToClasses (traits), target, action);
}
/// <summary>
/// Registers a selector that will be called on the current object when any of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="action">The selector to call on the current object.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public IUITraitChangeRegistration RegisterForTraitChanges (Type [] traits, Selector action)
{
return RegisterForTraitChanges (ToClasses (traits), action);
}
#if !XAMCORE_5_0
[BindingImpl (BindingImplOptions.Optimizable)]
#if !NET
public IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, global::System.Action<IUITraitEnvironment, UITraitCollection> handler)
{
// The manual block code is somewhat annoying to implement, so at least don't do it twice (once for .NET and once for legacy Xamarin) unless we really need to.
throw new NotImplementedException ("This API has not been implemented for legacy Xamarin. Please upgrade to .NET");
}
#else
/// <summary>
/// Registers a selector that will be called on the specified object when any of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="handler">The callback to execute when any of the specified traits changes.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
public unsafe IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, [BlockProxy (typeof (ObjCRuntime.Trampolines.IUITraitChangeObservable_RegisterForTraitChanges_NIDAction))] global::System.Action<IUITraitEnvironment, UITraitCollection> handler)
{
global::UIKit.UIApplication.EnsureUIThread ();
if (traits is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (traits));
if (handler is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (handler));
using var nsa_traits = NSArray.FromNSObjects (traits);
using var block_handler = Trampolines.IUITraitChangeObservable_RegisterForTraitChanges_SDAction.CreateBlock (handler);
return Runtime.GetINativeObject<IUITraitChangeRegistration> (NativeHandle_objc_msgSend_NativeHandle_BlockLiteral (this.Handle, Selector.GetHandle ("registerForTraitChanges:withHandler:"), nsa_traits.Handle, &block_handler), false)!;
}
#endif
/// <summary>
/// Registers a selector that will be called on the specified object when any of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="target">The object whose specified selector will be called.</param>
/// <param name="action">The selector to call on the specified object.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
[BindingImpl (BindingImplOptions.Optimizable)]
public IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, NSObject target, Selector action)
{
global::UIKit.UIApplication.EnsureUIThread ();
if (traits is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (traits));
var target__handle__ = target!.GetNonNullHandle (nameof (target));
var action__handle__ = action!.GetNonNullHandle (nameof (action));
using var nsa_traits = NSArray.FromNSObjects (traits);
return Runtime.GetINativeObject<IUITraitChangeRegistration> (NativeHandle_objc_msgSend_NativeHandle_NativeHandle_NativeHandle (this.Handle, Selector.GetHandle ("registerForTraitChanges:withTarget:action:"), nsa_traits.Handle, target__handle__, action.Handle), false)!;
}
/// <summary>
/// Registers a selector that will be called on the specified object when any of the specified traits changes.
/// </summary>
/// <param name="traits">The traits to observe.</param>
/// <param name="action">The selector to call on the current object.</param>
/// <returns>A token that can be used to unregister the callback by calling <see cref="M:UnregisterForTraitChanges" />.</returns>
[BindingImpl (BindingImplOptions.Optimizable)]
public IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, Selector action)
{
global::UIKit.UIApplication.EnsureUIThread ();
if (traits is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (traits));
var action__handle__ = action!.GetNonNullHandle (nameof (action));
using var nsa_traits = NSArray.FromNSObjects (traits);
return Runtime.GetINativeObject<IUITraitChangeRegistration> (NativeHandle_objc_msgSend_NativeHandle_NativeHandle (this.Handle, Selector.GetHandle ("registerForTraitChanges:withAction:"), nsa_traits.Handle, action.Handle), false)!;
}
static Class [] ToClasses (IUITraitDefinition [] traits)
{
if (traits is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (traits));
var traitsClasses = new Class [traits.Length];
for (var i = 0; i < traits.Length; i++)
traitsClasses [i] = new Class (traits [i].GetType ());
return traitsClasses;
}
[EditorBrowsable (EditorBrowsableState.Never)]
[Obsolete ("Use the 'UITraitChangeObservable.RegisterForTraitChanges (Class[], Action<IUITraitEnvironment, UITraitCollection>)' method instead.")]
public IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, Action<IUITraitEnvironment, UITraitCollection> handler)
{
return RegisterForTraitChanges (ToClasses (traits), handler);
}
[EditorBrowsable (EditorBrowsableState.Never)]
[Obsolete ("Use the 'UITraitChangeObservable.RegisterForTraitChanges (Class[], NSObject, Selector)' method instead.")]
public IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, NSObject target, Selector action)
{
return RegisterForTraitChanges (ToClasses (traits), target, action);
}
[EditorBrowsable (EditorBrowsableState.Never)]
[Obsolete ("Use the 'UITraitChangeObservable.RegisterForTraitChanges (Class[], Selector)' method instead.")]
public IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, Selector action)
{
return RegisterForTraitChanges (ToClasses (traits), action);
}
[DllImport (Messaging.LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
extern static NativeHandle NativeHandle_objc_msgSend_NativeHandle_NativeHandle (IntPtr receiver, IntPtr selector, NativeHandle arg1, NativeHandle arg2);
[DllImport (Messaging.LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
extern unsafe static NativeHandle NativeHandle_objc_msgSend_NativeHandle_BlockLiteral (IntPtr receiver, IntPtr selector, NativeHandle arg1, BlockLiteral* arg2);
[DllImport (Messaging.LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
extern static NativeHandle NativeHandle_objc_msgSend_NativeHandle_NativeHandle_NativeHandle (IntPtr receiver, IntPtr selector, NativeHandle arg1, NativeHandle arg2, NativeHandle arg3);
#endif // !XAMCORE_5_0
}
}
#if !XAMCORE_5_0 && NET
namespace ObjCRuntime {
using UIKit;
static partial class Trampolines {
[UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl)]
[UserDelegateType (typeof (global::System.Action<global::UIKit.IUITraitEnvironment, global::UIKit.UITraitCollection>))]
unsafe internal delegate void IUITraitChangeObservable_RegisterForTraitChanges_Callback (IntPtr block, NativeHandle arg1, NativeHandle arg2);
static internal class IUITraitChangeObservable_RegisterForTraitChanges_SDAction {
[Preserve (Conditional = true)]
[UnmanagedCallersOnly]
internal static unsafe void Invoke (IntPtr block, NativeHandle arg1, NativeHandle arg2)
{
var del = BlockLiteral.GetTarget<global::System.Action<global::UIKit.IUITraitEnvironment, global::UIKit.UITraitCollection>> (block);
if (del is not null) {
del (Runtime.GetINativeObject<UIKit.IUITraitEnvironment> (arg1, false)!, Runtime.GetNSObject<UITraitCollection> (arg2)!);
}
}
internal static unsafe BlockLiteral CreateNullableBlock (global::System.Action<global::UIKit.IUITraitEnvironment, global::UIKit.UITraitCollection>? callback)
{
if (callback is null)
return default (BlockLiteral);
return CreateBlock (callback);
}
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
internal static unsafe BlockLiteral CreateBlock (global::System.Action<global::UIKit.IUITraitEnvironment, global::UIKit.UITraitCollection> callback)
{
delegate* unmanaged<IntPtr, NativeHandle, NativeHandle, void> trampoline = &Invoke;
return new BlockLiteral (trampoline, callback, typeof (IUITraitChangeObservable_RegisterForTraitChanges_SDAction), nameof (Invoke));
}
}
internal sealed class IUITraitChangeObservable_RegisterForTraitChanges_NIDAction : TrampolineBlockBase {
IUITraitChangeObservable_RegisterForTraitChanges_Callback invoker;
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public unsafe IUITraitChangeObservable_RegisterForTraitChanges_NIDAction (BlockLiteral* block) : base (block)
{
invoker = block->GetDelegateForBlock<IUITraitChangeObservable_RegisterForTraitChanges_Callback> ();
}
[Preserve (Conditional = true)]
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public unsafe static global::System.Action<global::UIKit.IUITraitEnvironment, global::UIKit.UITraitCollection>? Create (IntPtr block)
{
if (block == IntPtr.Zero)
return null;
var del = (global::System.Action<global::UIKit.IUITraitEnvironment, global::UIKit.UITraitCollection>) GetExistingManagedDelegate (block);
return del ?? new IUITraitChangeObservable_RegisterForTraitChanges_NIDAction ((BlockLiteral*) block).Invoke;
}
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
unsafe void Invoke (global::UIKit.IUITraitEnvironment arg1, global::UIKit.UITraitCollection arg2)
{
var arg1__handle__ = arg1.GetHandle ();
var arg2__handle__ = arg2.GetHandle ();
invoker (BlockPointer, arg1__handle__, arg2__handle__);
}
}
}
}
#endif // !XAMCORE_5_0 && NET
#endif // !__WATCHOS__

Просмотреть файл

@ -0,0 +1,101 @@
//
// UITraitOverrides.cs: support for UITraitOverrides
//
// Authors:
// Rolf Bjarne Kvinge
//
// Copyright 2023 Microsoft Corp. All rights reserved.
//
#if !__WATCHOS__
using System;
using Foundation;
using ObjCRuntime;
#nullable enable
namespace UIKit {
public partial interface IUITraitOverrides {
/// <summary>
/// Check whether the specified trait is overridden.
/// </summary>
/// <typeparam name="T">The trait to check for.</typeparam>
/// <returns>True if the specified trait is overridden.</returns>
[BindingImpl (BindingImplOptions.Optimizable)]
public sealed bool ContainsTrait<T> () where T : IUITraitDefinition
{
return ContainsTrait (typeof (T));
}
/// <summary>
/// Removes the specified trait override.
/// </summary>
/// <typeparam name="T">The trait to remove.</typeparam>
[BindingImpl (BindingImplOptions.Optimizable)]
public sealed void RemoveTrait<T> () where T : IUITraitDefinition
{
RemoveTrait (typeof (T));
}
/// <summary>
/// Check whether the specified trait is overridden.
/// </summary>
/// <param name="trait">The trait to check for.</param>
/// <returns>True if the specified trait is overridden.</returns>
[BindingImpl (BindingImplOptions.Optimizable)]
public sealed bool ContainsTrait (Type trait)
{
return ContainsTrait (new Class (trait));
}
/// <summary>
/// Removes the specified trait override.
/// </summary>
/// <param name="trait">The trait to remove.</param>
[BindingImpl (BindingImplOptions.Optimizable)]
public sealed void RemoveTrait (Type trait)
{
RemoveTrait (new Class (trait));
}
#if !XAMCORE_5_0
/// <summary>
/// Check whether the specified trait is overridden.
/// </summary>
/// <param name="trait">The trait to check for.</param>
/// <returns>True if the specified trait is overridden.</returns>
[BindingImpl (BindingImplOptions.Optimizable)]
public sealed bool ContainsTrait (Class trait)
{
global::UIKit.UIApplication.EnsureUIThread ();
var trait__handle__ = trait!.GetNonNullHandle (nameof (trait));
#if NET
var ret = global::ObjCRuntime.Messaging.bool_objc_msgSend_NativeHandle (this.Handle, Selector.GetHandle ("containsTrait:"), trait__handle__);
#else
var ret = global::ObjCRuntime.Messaging.bool_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle ("containsTrait:"), trait__handle__);
#endif
return ret != 0;
}
/// <summary>
/// Removes the specified trait override.
/// </summary>
/// <param name="trait">The trait to remove.</param>
[BindingImpl (BindingImplOptions.Optimizable)]
public sealed void RemoveTrait (Class trait)
{
global::UIKit.UIApplication.EnsureUIThread ();
var trait__handle__ = trait!.GetNonNullHandle (nameof (trait));
#if NET
global::ObjCRuntime.Messaging.void_objc_msgSend_NativeHandle (this.Handle, Selector.GetHandle ("removeTrait:"), trait__handle__);
#else
global::ObjCRuntime.Messaging.void_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle ("removeTrait:"), trait__handle__);
#endif
}
#endif // !XAMCORE_5_0
}
}
#endif // !__WATCHOS__

Просмотреть файл

@ -1781,6 +1781,8 @@ UIKIT_SOURCES = \
UIKit/UITextAttributes.cs \ UIKit/UITextAttributes.cs \
UIKit/UITextField.cs \ UIKit/UITextField.cs \
UIKit/UITextView.cs \ UIKit/UITextView.cs \
UIKit/UITraitChangeObservable.cs \
UIKit/UITraitOverrides.cs \
UIKit/UITraitCollection.cs \ UIKit/UITraitCollection.cs \
UIKit/UIToolbar.cs \ UIKit/UIToolbar.cs \
UIKit/UIVibrancyEffect.cs \ UIKit/UIVibrancyEffect.cs \

Просмотреть файл

@ -12058,7 +12058,8 @@ namespace UIKit {
[MacCatalyst (13, 1)] [MacCatalyst (13, 1)]
[BaseType (typeof (NSObject))] [BaseType (typeof (NSObject))]
[DisableDefaultCtor] // NSInvalidArgumentException Reason: Don't call -[UIPresentationController init]. [DisableDefaultCtor] // NSInvalidArgumentException Reason: Don't call -[UIPresentationController init].
partial interface UIPresentationController : UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment { partial interface UIPresentationController : UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment
, UITraitChangeObservable {
[Export ("initWithPresentedViewController:presentingViewController:")] [Export ("initWithPresentedViewController:presentingViewController:")]
[DesignatedInitializer] [DesignatedInitializer]
NativeHandle Constructor (UIViewController presentedViewController, [NullAllowed] UIViewController presentingViewController); NativeHandle Constructor (UIViewController presentedViewController, [NullAllowed] UIViewController presentingViewController);
@ -16290,6 +16291,7 @@ namespace UIKit {
[MacCatalyst (13, 1)] [MacCatalyst (13, 1)]
[BaseType (typeof (UIResponder))] [BaseType (typeof (UIResponder))]
interface UIView : UIAppearance, UIAppearanceContainer, UIAccessibility, UIDynamicItem, NSCoding, UIAccessibilityIdentification, UITraitEnvironment, UICoordinateSpace, UIFocusItem, UIFocusItemContainer interface UIView : UIAppearance, UIAppearanceContainer, UIAccessibility, UIDynamicItem, NSCoding, UIAccessibilityIdentification, UITraitEnvironment, UICoordinateSpace, UIFocusItem, UIFocusItemContainer
, UITraitChangeObservable
#if !TVOS #if !TVOS
, UILargeContentViewerItem, UIPopoverPresentationControllerSourceItem , UILargeContentViewerItem, UIPopoverPresentationControllerSourceItem
#endif #endif
@ -17080,7 +17082,8 @@ namespace UIKit {
[NoWatch] [NoWatch]
[MacCatalyst (13, 1)] [MacCatalyst (13, 1)]
[BaseType (typeof (UIResponder))] [BaseType (typeof (UIResponder))]
interface UIViewController : NSCoding, UIAppearanceContainer, UIContentContainer, UITraitEnvironment, UIFocusEnvironment, NSExtensionRequestHandling { interface UIViewController : NSCoding, UIAppearanceContainer, UIContentContainer, UITraitEnvironment, UIFocusEnvironment, NSExtensionRequestHandling
, UITraitChangeObservable {
[DesignatedInitializer] [DesignatedInitializer]
[Export ("initWithNibName:bundle:")] [Export ("initWithNibName:bundle:")]
[PostGet ("NibBundle")] [PostGet ("NibBundle")]
@ -18216,19 +18219,57 @@ namespace UIKit {
[return: NullAllowed] [return: NullAllowed]
NSObject GetObject (IUIObjectTraitDefinition trait); NSObject GetObject (IUIObjectTraitDefinition trait);
#if !XAMCORE_5_0
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)] [Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Export ("changedTraitsFromTraitCollection:")] [Export ("changedTraitsFromTraitCollection:")]
[Obsolete ("Use 'GetChangedTraits2' instead.")]
NSSet<IUITraitDefinition> GetChangedTraits ([NullAllowed] UITraitCollection traitCollection); NSSet<IUITraitDefinition> GetChangedTraits ([NullAllowed] UITraitCollection traitCollection);
#endif
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Export ("changedTraitsFromTraitCollection:")]
#if XAMCORE_5_0
NSSet<Class> GetChangedTraits ([NullAllowed] UITraitCollection traitCollection);
#else
[Sealed]
NSSet<Class> GetChangedTraits2 ([NullAllowed] UITraitCollection traitCollection);
#endif
#if !XAMCORE_5_0
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Static]
[Export ("systemTraitsAffectingColorAppearance")]
[Obsolete ("Use 'SystemTraitsAffectingColorAppearance2' instead.")]
IUITraitDefinition [] SystemTraitsAffectingColorAppearance { get; }
#endif
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)] [Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Static] [Static]
[Export ("systemTraitsAffectingColorAppearance")] [Export ("systemTraitsAffectingColorAppearance")]
IUITraitDefinition [] SystemTraitsAffectingColorAppearance { get; } #if XAMCORE_5_0
Class [] SystemTraitsAffectingColorAppearance { get; }
#else
[Sealed]
Class [] SystemTraitsAffectingColorAppearance2 { get; }
#endif
#if !XAMCORE_5_0
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Static]
[Export ("systemTraitsAffectingImageLookup")]
[Obsolete ("Use 'SystemTraitsAffectingImageLookup2' instead.")]
IUITraitDefinition [] SystemTraitsAffectingImageLookup { get; }
#endif
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)] [Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Static] [Static]
[Export ("systemTraitsAffectingImageLookup")] [Export ("systemTraitsAffectingImageLookup")]
IUITraitDefinition [] SystemTraitsAffectingImageLookup { get; } #if XAMCORE_5_0
Class [] SystemTraitsAffectingImageLookup { get; }
#else
[Sealed]
Class [] SystemTraitsAffectingImageLookup2 { get; }
#endif
[Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)] [Watch (10, 0), TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Export ("typesettingLanguage")] [Export ("typesettingLanguage")]
@ -24044,7 +24085,8 @@ namespace UIKit {
[MacCatalyst (13, 1)] [MacCatalyst (13, 1)]
[BaseType (typeof (UIScene))] [BaseType (typeof (UIScene))]
[DisableDefaultCtor] [DisableDefaultCtor]
interface UIWindowScene { interface UIWindowScene :
UITraitChangeObservable {
[Export ("initWithSession:connectionOptions:")] [Export ("initWithSession:connectionOptions:")]
[DesignatedInitializer] [DesignatedInitializer]
@ -28378,11 +28420,21 @@ namespace UIKit {
interface UITraitOverrides : UIMutableTraits { interface UITraitOverrides : UIMutableTraits {
[Abstract] [Abstract]
[Export ("containsTrait:")] [Export ("containsTrait:")]
#if XAMCORE_5_0
bool ContainsTrait (Class trait);
#else
[Obsolete ("Use 'ContainsTrait<T> ()', 'ContainsTrait (Type)' or 'ContainsTrait (Class)' instead.")]
bool ContainsTrait (IUITraitDefinition trait); bool ContainsTrait (IUITraitDefinition trait);
#endif
[Abstract] [Abstract]
[Export ("removeTrait:")] [Export ("removeTrait:")]
#if XAMCORE_5_0
void RemoveTrait (Class trait);
#else
[Obsolete ("Use 'RemoveTrait<T> ()', 'RemoveTrait (Type)' or 'RemoveTrait (Class)' instead.")]
void RemoveTrait (IUITraitDefinition trait); void RemoveTrait (IUITraitDefinition trait);
#endif
} }
[iOS (17, 0), TV (17, 0), Watch (10, 0), MacCatalyst (17, 0)] [iOS (17, 0), TV (17, 0), Watch (10, 0), MacCatalyst (17, 0)]
@ -28484,21 +28536,41 @@ namespace UIKit {
[NoWatch, TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)] [NoWatch, TV (17, 0), iOS (17, 0), MacCatalyst (17, 0)]
[Protocol] [Protocol]
interface UITraitChangeObservable { interface UITraitChangeObservable {
#if XAMCORE_5_0
[Abstract] [Abstract]
#endif
[Export ("registerForTraitChanges:withHandler:")] [Export ("registerForTraitChanges:withHandler:")]
#if XAMCORE_5_0
IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, Action<IUITraitEnvironment, UITraitCollection> handler);
#else
[Obsolete ("Use the 'UITraitChangeObservable.RegisterForTraitChanges (Class[], Action<IUITraitEnvironment, UITraitCollection>)' method instead.")]
IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, Action<IUITraitEnvironment, UITraitCollection> handler); IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, Action<IUITraitEnvironment, UITraitCollection> handler);
#endif
#if XAMCORE_5_0
[Abstract] [Abstract]
#endif
[Export ("registerForTraitChanges:withTarget:action:")] [Export ("registerForTraitChanges:withTarget:action:")]
#if XAMCORE_5_0
IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, NSObject target, Selector action);
#else
[Obsolete ("Use the 'UITraitChangeObservable.RegisterForTraitChanges (Class[], NSObject, Selector)' method instead.")]
IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, NSObject target, Selector action); IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, NSObject target, Selector action);
#endif
#if XAMCORE_5_0
[Abstract] [Abstract]
#endif
[Export ("registerForTraitChanges:withAction:")] [Export ("registerForTraitChanges:withAction:")]
#if XAMCORE_5_0
IUITraitChangeRegistration RegisterForTraitChanges (Class [] traits, Selector action);
#else
[Obsolete ("Use the 'UITraitChangeObservable.RegisterForTraitChanges (Class[], Selector)' method instead.")]
IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, Selector action); IUITraitChangeRegistration RegisterForTraitChanges (IUITraitDefinition [] traits, Selector action);
#endif
[Abstract] [Abstract]
[Export ("unregisterForTraitChanges:")] [Export ("unregisterForTraitChanges:")]
void UnregisterForTraitChanges (IUITraitChangeRegistration registration); void UnregisterForTraitChanges (IUITraitChangeRegistration registration);
} }
} }

Просмотреть файл

@ -0,0 +1,176 @@
//
// Unit tests for UITraitOverrides
//
// Authors:
// Rolf Bjarne Kvinge <rolf@xamarin.com>
//
// Copyright 2023 Microsoft Corp. All rights reserved.
//
#if !__WATCHOS__ && !__MACOS__ && NET
using System;
using System.IO;
using System.Reflection;
using System.Threading;
using Foundation;
using UIKit;
using ObjCRuntime;
using NUnit.Framework;
using Xamarin.Utils;
namespace MonoTouchFixtures.UIKit {
[TestFixture]
[Preserve (AllMembers = true)]
public class UITraitOverridesTest {
[Test]
public void RegisterForTraitChanges_ClassArray ()
{
TestRuntime.AssertXcodeVersion (15, 0);
CallbackTest ((vc, callback) => {
return vc.RegisterForTraitChanges (new [] {
new Class (typeof (UITraitVerticalSizeClass)),
new Class (typeof (UITraitHorizontalSizeClass)),
}, callback);
}, "ClassArray ");
}
[Test]
public void RegisterForTraitChanges_TypeArray ()
{
TestRuntime.AssertXcodeVersion (15, 0);
CallbackTest ((vc, callback) => {
return vc.RegisterForTraitChanges (new [] {
typeof (UITraitVerticalSizeClass),
typeof (UITraitHorizontalSizeClass),
}, callback);
}, "TypeArray ");
}
[Test]
public void RegisterForTraitChanges_ParamsTypeArray ()
{
TestRuntime.AssertXcodeVersion (15, 0);
CallbackTest ((vc, callback) => {
return vc.RegisterForTraitChanges (callback,
typeof (UITraitVerticalSizeClass),
typeof (UITraitHorizontalSizeClass));
}, "ParamsTypeArray ");
}
[Test]
public void RegisterForTraitChanges_Generic ()
{
TestRuntime.AssertXcodeVersion (15, 0);
CallbackTest ((vc, callback) => {
// return vc.RegisterForTraitChanges<NSObject> (callback);
return vc.RegisterForTraitChanges<UITraitHorizontalSizeClass, UITraitVerticalSizeClass> (callback);
}, "Generic ");
}
void CallbackTest (Func<IUITraitChangeObservable, Action<IUITraitEnvironment, UITraitCollection>, IUITraitChangeRegistration> registerFunc, string prefix)
{
TestRuntime.AssertXcodeVersion (15, 0);
using var vc = new UIViewController ();
using var label = new UILabel () {
TextAlignment = UITextAlignment.Center,
};
vc.View!.AddSubview (label);
UIUserInterfaceSizeClass? horizontal = null;
UIUserInterfaceSizeClass? vertical = null;
var msgPrefix = "?";
var callbackCounter = 0;
Exception? ex = null;
Action<IUITraitEnvironment, UITraitCollection> callback = (env, coll) => {
try {
Assert.AreEqual (horizontal is not null, vc.TraitOverrides.ContainsTrait<UITraitHorizontalSizeClass> (), $"{prefix}{msgPrefix} Horizontal A");
Assert.AreEqual (horizontal is not null, vc.TraitOverrides.ContainsTrait (typeof (UITraitHorizontalSizeClass)), $"{prefix}{msgPrefix} Horizontal B");
Assert.AreEqual (horizontal is not null, vc.TraitOverrides.ContainsTrait (new Class (typeof (UITraitHorizontalSizeClass))), $"{prefix}{msgPrefix} Horizontal C");
Assert.AreEqual (vertical is not null, vc.TraitOverrides.ContainsTrait<UITraitVerticalSizeClass> (), $"{prefix}{msgPrefix} Vertical A");
Assert.AreEqual (vertical is not null, vc.TraitOverrides.ContainsTrait (typeof (UITraitVerticalSizeClass)), $"{prefix}{msgPrefix} Vertical B");
Assert.AreEqual (vertical is not null, vc.TraitOverrides.ContainsTrait (new Class (typeof (UITraitVerticalSizeClass))), $"{prefix}{msgPrefix} Vertical C");
if (horizontal is not null) {
Assert.AreEqual (horizontal.Value, vc.TraitOverrides.HorizontalSizeClass, $"{prefix}{msgPrefix} Horizontal Value");
}
if (vertical is not null) {
Assert.AreEqual (vertical.Value, vc.TraitOverrides.VerticalSizeClass, $"{prefix}{msgPrefix} Vertical Value");
}
callbackCounter++;
} catch (Exception e) {
ex = e;
}
};
// Figure out the initial values so that we can choose a different value when setting them.
var tc = UITraitCollection.CurrentTraitCollection;
UIUserInterfaceSizeClass? initialHorizonal = null;
UIUserInterfaceSizeClass? initialVertical = null;
tc.PerformAsCurrentTraitCollection (() => {
initialHorizonal = tc.HorizontalSizeClass;
initialVertical = tc.VerticalSizeClass;
});
var firstHorizontal = (initialHorizonal == UIUserInterfaceSizeClass.Regular) ? UIUserInterfaceSizeClass.Compact : UIUserInterfaceSizeClass.Regular;
var firstVertical = (initialVertical == UIUserInterfaceSizeClass.Regular) ? UIUserInterfaceSizeClass.Compact : UIUserInterfaceSizeClass.Regular;
var secondHorizontal = (initialHorizonal == UIUserInterfaceSizeClass.Regular) ? UIUserInterfaceSizeClass.Regular : UIUserInterfaceSizeClass.Compact;
var secondVertical = (initialVertical == UIUserInterfaceSizeClass.Regular) ? UIUserInterfaceSizeClass.Regular : UIUserInterfaceSizeClass.Compact;
var token = registerFunc (vc, callback);
horizontal = firstHorizontal;
vc.TraitOverrides.HorizontalSizeClass = horizontal.Value;
Assert.AreEqual (1, callbackCounter, $"{prefix}CallbackCounter 1");
Assert.IsNull (ex, $"{prefix}Exception 1");
horizontal = secondHorizontal;
vc.TraitOverrides.HorizontalSizeClass = horizontal.Value;
Assert.AreEqual (2, callbackCounter, $"{prefix}CallbackCounter 2");
Assert.IsNull (ex, $"{prefix}Exception 2");
vertical = firstVertical;
vc.TraitOverrides.VerticalSizeClass = vertical.Value;
Assert.AreEqual (3, callbackCounter, $"{prefix}CallbackCounter 3");
Assert.IsNull (ex, $"{prefix}Exception 3");
vertical = secondVertical;
vc.TraitOverrides.VerticalSizeClass = vertical.Value;
Assert.AreEqual (4, callbackCounter, $"{prefix}CallbackCounter 4");
Assert.IsNull (ex, $"{prefix}Exception 4");
vertical = null;
vc.TraitOverrides.RemoveTrait (typeof (UITraitVerticalSizeClass));
Assert.AreEqual (4, callbackCounter, $"{prefix}CallbackCounter 5");
Assert.IsNull (ex, $"{prefix}Exception 5");
horizontal = null;
vc.TraitOverrides.RemoveTrait<UITraitHorizontalSizeClass> ();
Assert.AreEqual (4, callbackCounter, $"{prefix}CallbackCounter 6");
Assert.IsNull (ex, $"{prefix}Exception 6");
horizontal = firstHorizontal;
vc.TraitOverrides.HorizontalSizeClass = horizontal.Value;
Assert.AreEqual (5, callbackCounter, $"{prefix}CallbackCounter 7");
Assert.IsNull (ex, $"{prefix}Exception 7");
horizontal = null;
vc.TraitOverrides.RemoveTrait (new Class (typeof (UITraitHorizontalSizeClass)));
Assert.AreEqual (5, callbackCounter, $"{prefix}CallbackCounter 8");
Assert.IsNull (ex, $"{prefix}Exception 8");
vc.UnregisterForTraitChanges (token);
}
}
}
#endif // !__WATCHOS__ && !__MACOS__

Просмотреть файл

@ -474,3 +474,9 @@
!incorrect-protocol-member! UIPopoverPresentationControllerSourceItem::frameInView: is REQUIRED and should be abstract !incorrect-protocol-member! UIPopoverPresentationControllerSourceItem::frameInView: is REQUIRED and should be abstract
!incorrect-protocol-member! UIMenuLeaf::selectedImage is REQUIRED and should be abstract !incorrect-protocol-member! UIMenuLeaf::selectedImage is REQUIRED and should be abstract
!incorrect-protocol-member! UIMenuLeaf::setSelectedImage: is REQUIRED and should be abstract !incorrect-protocol-member! UIMenuLeaf::setSelectedImage: is REQUIRED and should be abstract
# these were bound with an incorrect signature, and made optional so that customers wouldn't have to implement methods with broken signatures.
# this is fixed in XAMCORE_5_0
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withAction: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withHandler: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withTarget:action: is REQUIRED and should be abstract

Просмотреть файл

@ -408,3 +408,9 @@
# xamcore 5 changes # xamcore 5 changes
!incorrect-protocol-member! UIMenuLeaf::selectedImage is REQUIRED and should be abstract !incorrect-protocol-member! UIMenuLeaf::selectedImage is REQUIRED and should be abstract
!incorrect-protocol-member! UIMenuLeaf::setSelectedImage: is REQUIRED and should be abstract !incorrect-protocol-member! UIMenuLeaf::setSelectedImage: is REQUIRED and should be abstract
# these were bound with an incorrect signature, and made optional so that customers wouldn't have to implement methods with broken signatures.
# this is fixed in XAMCORE_5_0
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withAction: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withHandler: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withTarget:action: is REQUIRED and should be abstract

Просмотреть файл

@ -651,3 +651,9 @@
# not really needed, seems that xtro is confused # not really needed, seems that xtro is confused
!missing-requires-super! UIControl::contextMenuInteraction:willDisplayMenuForConfiguration:animator: is missing an [RequiresSuper] attribute !missing-requires-super! UIControl::contextMenuInteraction:willDisplayMenuForConfiguration:animator: is missing an [RequiresSuper] attribute
!missing-requires-super! UIControl::contextMenuInteraction:willEndForConfiguration:animator: is missing an [RequiresSuper] attribute !missing-requires-super! UIControl::contextMenuInteraction:willEndForConfiguration:animator: is missing an [RequiresSuper] attribute
# these were bound with an incorrect signature, and made optional so that customers wouldn't have to implement methods with broken signatures.
# this is fixed in XAMCORE_5_0
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withAction: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withHandler: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withTarget:action: is REQUIRED and should be abstract

Просмотреть файл

@ -567,3 +567,9 @@
# added and deprecated on xcode 15 # added and deprecated on xcode 15
!missing-selector! UIControlUIControl::contextMenuInteraction:previewForDismissingMenuWithConfiguration: not bound !missing-selector! UIControlUIControl::contextMenuInteraction:previewForDismissingMenuWithConfiguration: not bound
!missing-selector! UIControlUIControl::contextMenuInteraction:previewForHighlightingMenuWithConfiguration: not bound !missing-selector! UIControlUIControl::contextMenuInteraction:previewForHighlightingMenuWithConfiguration: not bound
# these were bound with an incorrect signature, and made optional so that customers wouldn't have to implement methods with broken signatures.
# this is fixed in XAMCORE_5_0
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withAction: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withHandler: is REQUIRED and should be abstract
!incorrect-protocol-member! UITraitChangeObservable::registerForTraitChanges:withTarget:action: is REQUIRED and should be abstract