C# &引用;尝试呈现Xamarin“窗体”“平台”“iOS”“ModalWrapper,其视图不在窗口层次结构中”;UIImagePickerController出错

C# &引用;尝试呈现Xamarin“窗体”“平台”“iOS”“ModalWrapper,其视图不在窗口层次结构中”;UIImagePickerController出错,c#,.net,swift,xamarin,xamarin.ios,C#,.net,Swift,Xamarin,Xamarin.ios,我有一个基于Xamarin.Forms的应用程序,运行在Android和iOS上。现在,我正在实现从相机卷中选择图像并将其上传到服务器的功能。因此,我正在为iOS编写特定于平台的代码,这就是错误发生的地方 我正在从特定于平台的iOS渲染器调用UIImagePickerController。它正常打开。但在UIImagePickerController中点击图像时,除了Visual Studio在调试控制台中显示一条消息外,什么也不会发生: “警告:尝试在Xamarin_Forms_Platfor

我有一个基于Xamarin.Forms的应用程序,运行在Android和iOS上。现在,我正在实现从相机卷中选择图像并将其上传到服务器的功能。因此,我正在为iOS编写特定于平台的代码,这就是错误发生的地方

我正在从特定于平台的iOS渲染器调用UIImagePickerController。它正常打开。但在UIImagePickerController中点击图像时,除了Visual Studio在调试控制台中显示一条消息外,什么也不会发生:

“警告:尝试在Xamarin_Forms_Platform_iOS_PlatformRenderer:0x153ead6a0上显示Xamarin_Forms_Platform_iOS_ModalWrapper:0x155a7ed00,其视图不在窗口层次结构中!”

我在谷歌上搜索,发现有人编写了一个名为“GetVisibleViewController”的函数,我将其改编为适合我的项目(你可以在下面看到)。在该函数返回的ViewController上,我调用PresentModalViewController()方法。不幸的是,它也不起作用。无法选择照片

private void ChoosePhoto()
{
_imagePicker=新的UIImagePickerController()
{
SourceType=UIImagePickerControllerSourceType.PhotoLibrary,
MediaTypes=新字符串[]{UTType.Image}
};
_imagePicker.FinishedPickingMedia+=委托(对象发送方,UIImagePickerDiapickeDeventargs e)
{
var fileName=eopAppLibrary.Tools.GetTimestampJpegFileName(“scantoop_iOS”);
var jpegImageData=e.OriginalImage.AsJPEG();
var jpegBytes=jpegImageData.ToArray();
Events.raiseFilePreviewEded(此,JPEG字节,文件名);
};
_imagePicker.Cancelled+=委托(对象发送方,事件参数e)
{
_imagePicker.DismissModalViewController(真);
};
var viewController=GetVisibleViewController();
viewController.PresentModalViewController(_imagePicker,true);
}
UIViewController GetVisibleViewController(UIViewController=null)
{
控制器=控制器??UIApplication.SharedApplication.KeyWindow.RootViewController;
如果(controller.PresentedViewController==null)
{
返回控制器;
}
如果(controller.PresentedViewController是UINavigationController)
{
返回((UINavigationController)controller.PresentedViewController.VisibleViewController;
}
如果(controller.PresentedViewController是UITabBarController)
{
返回((UITabBarController)控制器。显示视图控制器。选择视图控制器;
}
返回GetVisibleViewController(controller.PresentedViewController);
}

我们也遇到了类似的问题,下面是我们得出的结论:

    var topViewController = UIApplication.SharedApplication.KeyWindow.RootViewController;
    var controllerToPresentWith = topViewController.VisibleViewController();
    controllerToPresentWith.PresentModalViewController(_imagePicker, true);
然后

    ...
    public static UIViewController VisibleViewController(this UIViewController controller)
    {
        if (controller == null)
            return null;

        if (controller is UINavigationController navController)
        {
            return navController.VisibleViewController();
        }
        else if (controller is UITabBarController tabController)
        {
            tabController.SelectedViewController?.VisibleViewController();
        }
        else
        {
            var vc =  controller.PresentedViewController?.VisibleViewController();
            if (vc != null)
                return vc;
        }
        return controller;
    }

最后,我使用James Montemagno的媒体插件库(可通过NuGet:)和权限插件()实现了这一点

我为此编写了以下代码:

private async Task ChoosePhoto()
{
    var permission = await CheckCameraRollPermission();

    if (permission == PermissionStatus.Granted)
    {
        await CrossMedia.Current.Initialize();

        // Show image picker dialog
        var file = await CrossMedia.Current.PickPhotoAsync(new Plugin.Media.Abstractions.PickMediaOptions()
        {
            ModalPresentationStyle = Plugin.Media.Abstractions.MediaPickerModalPresentationStyle.OverFullScreen
        });

        if (file != null)
        {
            // Image has been selected
            using (var stream = file.GetStream())
            {
                using (var memoryStream = new System.IO.MemoryStream())
                {
                    stream.CopyTo(memoryStream);

                    var fileBytes = memoryStream.ToArray();

                    // DO WHATEVER YOU WANT TO DO WITH THE SELECTED IMAGE AT THIS POINT
                }
            }
        }
    }
}

private async Task<PermissionStatus> CheckCameraRollPermission()
{
    // Check permission for image library access
    var permission = await PermissionsImplementation.Current.CheckPermissionStatusAsync(Permission.Photos);

    if (permission != PermissionStatus.Granted)
    {
        // Permission has not been granted -> if permission has been requested before and the user did not grant it, show message and return the permission
        var message = "";

        switch (permission)
        {
            case PermissionStatus.Denied:
            case PermissionStatus.Restricted:
                message = "Unfortunately, you did not grant permission to access the camera roll. If you want to change this, you can do so in the system settings of your device.";
                break;
            default:
                break;
        }

        if (!string.IsNullOrEmpty(message))
        {
            // Message available -> Display alert and return the permission
            var alert = UIAlertController.Create("Permission not granted", message, UIAlertControllerStyle.Alert);
            alert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));

            PresentViewController(alert, true, null);
            return permission;
        }

        // In all other cases, request the permission
        await PermissionsImplementation.Current.RequestPermissionsAsync(Permission.Photos);

        // Check for permission one more time and return it
        permission = await PermissionsImplementation.Current.CheckPermissionStatusAsync(Permission.Photos);
    }

    return permission;
}
专用异步任务ChoosePhoto()
{
var permission=wait CheckCameraRollPermission();
if(权限==权限状态.已授予)
{
等待CrossMedia.Current.Initialize();
//显示图像选择器对话框
var file=await CrossMedia.Current.PickPhotoAsync(新Plugin.Media.Abstractions.PickMediaOptions()
{
ModalPresentationStyle=Plugin.Media.Abstractions.MediaPickerModalPresentationStyle.OverFullScreen
});
如果(文件!=null)
{
//图像已被选中
使用(var stream=file.GetStream())
{
使用(var memoryStream=new System.IO.memoryStream())
{
stream.CopyTo(memoryStream);
var fileBytes=memoryStream.ToArray();
//此时,对所选图像执行任何操作
}
}
}
}
}
专用异步任务CheckCameraRollPermission()
{
//检查图像库访问权限
var permission=wait PermissionsImplementation.Current.CheckPermissionStatusAsync(permission.Photos);
if(权限!=权限状态.已授予)
{
//尚未授予权限->如果以前请求过权限,但用户未授予权限,则显示消息并返回权限
var message=“”;
切换(权限)
{
案例许可状态。拒绝:
案例许可状态。受限:
message=“很遗憾,您没有授予访问相机卷的权限。如果您想更改此权限,可以在设备的系统设置中进行更改。”;
打破
违约:
打破
}
如果(!string.IsNullOrEmpty(消息))
{
//消息可用->显示警报并返回权限
var alert=UIAlertController.Create(“未授予权限”,消息,UIAlertControllerStyle.alert);
AddAction(UIAlertAction.Create(“OK”,UIAlertActionStyle.Default,null));
PresentViewController(警报、真、空);
返回许可;
}
//在所有其他情况下,请请求许可
wait PermissionsImplementation.Current.RequestPermissionsAsync(Permission.Photos);
//再次检查权限并将其返回
权限=等待权限Simplementation.Current.CheckPermissionStatusAsync(权限.照片);
}
返回许可;
}

谢谢您的回答。不幸的是,这并没有解决问题。也许它与视图所属的选项卡页有关……可能是@Sebastian,在这种情况下,您必须更深入或更彻底地遍历您的层次结构。您可以在调试模式下使用“立即”窗口进行调试