How to resolve cannot convert from 'Foundation.NSObject[]' to 'Foundation.NSObject?' in iOS dependency service?

John Hardman 261 Reputation points
2020-11-30T13:07:34.647+00:00

The following code is work-in-progress. Once working, the intention is that it can be used on iOS to set the accessibility order of controls on a Xamarin.Forms ContentPage using a dependency service.

I am currently hitting two problems with this. The first is a compile-time error:
CS1503: Argument 2: cannot convert from 'Foundation.NSObject[]' to 'Foundation.NSObject?'
I have commented in the code where that is reported.

The second (if I comment out the code that doesn't compile) is that when debugging in Visual Studio, VS shows the nativeViews array as containing XF renderers, not UIViews. I assume that this is some VS weirdness, but could be wrong.

Can anybody assist with either of these, particularly the compile-time error?

    private IVisualElementRenderer GetRenderer(VisualElement xfVisualElement)
    {
        IVisualElementRenderer renderer = Platform.GetRenderer(xfVisualElement);
        if (renderer == null)
        {
            renderer = Platform.CreateRenderer(xfVisualElement);
            Platform.SetRenderer(xfVisualElement, renderer);
        }

        return renderer;
    }

    private UIView GetNativeView(VisualElement xfVisualElement) 
        => GetRenderer(xfVisualElement).NativeView;

    public void SetReadingOrder(VisualElement xfContainingElement, VisualElement[] xfVisualElements)
    {
        if (GetNativeView(xfContainingElement) is IUIAccessibilityContainer accessibilityContainer)
        {
            if (xfVisualElements.Length > 0)
            {
                NSObject[] nativeViews = new UIView[xfVisualElements.Length];

                int index = 0;
                foreach (VisualElement xfVisualElement in xfVisualElements)
                    nativeViews[index++] = GetNativeView(xfVisualElement).Self;

                // The following line results in the compile-time error
                // CS1503: Argument 2: cannot convert from 'Foundation.NSObject[]' to 'Foundation.NSObject?'
                accessibilityContainer.SetAccessibilityElements(nativeViews);
            }
            else
            {
                accessibilityContainer.SetAccessibilityElements(null);
            }
        }
    }

Note that if I look at the definition of UIAccessibilityContainer, it appears as follows:

namespace UIKit
{
    [Protocol(Name = "UIAccessibilityContainer", WrapperType = typeof(UIAccessibilityContainerWrapper), IsInformal = true)]
    [ProtocolMember(IsRequired = false, IsProperty = false, IsStatic = false, Name = "AccessibilityElementCount", Selector = "accessibilityElementCount", ReturnType = typeof(nint))]
    [ProtocolMember(IsRequired = false, IsProperty = false, IsStatic = false, Name = "GetAccessibilityElementAt", Selector = "accessibilityElementAtIndex:", ReturnType = typeof(NSObject), ParameterType = new[] { typeof(nint) }, ParameterByRef = new[] { false })]
    [ProtocolMember(IsRequired = false, IsProperty = false, IsStatic = false, Name = "GetIndexOfAccessibilityElement", Selector = "indexOfAccessibilityElement:", ReturnType = typeof(nint), ParameterType = new[] { typeof(NSObject) }, ParameterByRef = new[] { false })]
    [ProtocolMember(IsRequired = false, IsProperty = false, IsStatic = false, Name = "GetAccessibilityElements", Selector = "accessibilityElements", ReturnType = typeof(NSObject))]
    [ProtocolMember(IsRequired = false, IsProperty = false, IsStatic = false, Name = "SetAccessibilityElements", Selector = "setAccessibilityElements:", ParameterType = new[] { typeof(NSObject) }, ParameterByRef = new[] { false })]
    [ProtocolMember(IsRequired = false, IsProperty = true, IsStatic = false, Name = "AccessibilityContainerType", Selector = "accessibilityContainerType", PropertyType = typeof(UIAccessibilityContainerType), GetterSelector = "accessibilityContainerType", SetterSelector = "setAccessibilityContainerType:", ArgumentSemantic = ArgumentSemantic.Assign)]
    public interface IUIAccessibilityContainer : INativeObject, IDisposable
    {
    }
}
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,371 questions
0 comments No comments
{count} votes

Accepted answer
  1. John Hardman 261 Reputation points
    2020-11-30T15:55:59.36+00:00

    The line with the compile-time error, needed replacing with:

    accessibilityContainer.SetAccessibilityElements(NSArray.FromNSObjects(nativeViews));
    

    Having done that, the accessibility order seems to be set as expected.
    (Note that I haven't checked for resource leaks yet, so the code shown might not be 100% yet).

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. acmeaney 76 Reputation points
    2020-11-30T15:01:45.09+00:00

    SetAccessibilityElements takes an NSObject, which an array of NSObjects is not.

    You have to pass the method the type it expects for the code to work.

    I assume that the object nativeViews is supposed to be wrapped in something, but I am unfamiliar with accessibility so you will have to do some more research.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.