UIImagePickerController 出现“尝试呈现其视图不在窗口层次结构中的 Xamarin_Forms_Platform_iOS_ModalWrapper”错误

Seb*_*ian 5 .net c# xamarin.ios xamarin swift

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

我正在从特定于平台的 iOS 渲染器调用 UIImagePickerController。它正常打开。但是当点击 UIImagePickerController 中的图像时,没有任何反应,除了 Visual Studio 在调试控制台中显示一条消息:

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

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

private void ChoosePhoto()
{
    _imagePicker = new UIImagePickerController()
    {
        SourceType = UIImagePickerControllerSourceType.PhotoLibrary,
        MediaTypes = new string[] { UTType.Image }
    };

    _imagePicker.FinishedPickingMedia += delegate (object sender, UIImagePickerMediaPickedEventArgs e)
    {
        var fileName = eopAppLibrary.Tools.GetTimestampJpegFileName("ScanToEop_iOS");
        var jpegImageData = e.OriginalImage.AsJPEG();
        var jpegBytes = jpegImageData.ToArray();

        Events.RaiseFilePreviewNeeded(this, jpegBytes, fileName);
    };

    _imagePicker.Canceled += delegate (object sender, EventArgs e)
    {
        _imagePicker.DismissModalViewController(true);
    };

    var viewController = GetVisibleViewController();
    viewController.PresentModalViewController(_imagePicker, true);
}
Run Code Online (Sandbox Code Playgroud)
UIViewController GetVisibleViewController(UIViewController controller = null)
{
    controller = controller ?? UIApplication.SharedApplication.KeyWindow.RootViewController;

    if (controller.PresentedViewController == null)
    {
        return controller;
    }

    if (controller.PresentedViewController is UINavigationController)
    {
        return ((UINavigationController)controller.PresentedViewController).VisibleViewController;
    }

    if (controller.PresentedViewController is UITabBarController)
    {
        return ((UITabBarController)controller.PresentedViewController).SelectedViewController;
    }

    return GetVisibleViewController(controller.PresentedViewController);
}
Run Code Online (Sandbox Code Playgroud)

Seb*_*ian 0

最后,我通过使用 James Montemagno 的媒体插件库(可通过 NuGet 获取:https: //www.nuget.org/packages/Xam.Plugin.Media)和权限插件 ( https://www.nuget.org /packages/Plugin.Permissions)。

我为此编写了以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)