iOS Monotouch UIImagePickerController来自相机的多张照片/视频 [英] iOS Monotouch UIImagePickerController multiple photos / videos from camera

查看:65
本文介绍了iOS Monotouch UIImagePickerController来自相机的多张照片/视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用UIImagePickerController遇到一个奇怪的问题.在我们的应用程序中,用户可以填写一系列表格,还可以在这些表格中附加图像和视频.

We're experiencing a strange problem with a UIImagePickerController. In our application users are able to fill out a series of forms and also attach images and videos within these forms.

我们允许用户从相机胶卷中添加多张照片/视频,或者在填写表单时将其捕获.

We allow users to add multiple photos / videos either from the camera roll or to be captured at the time of filling the form out.

我们正在使用UIImagePickerController来做到这一点.用相机拍摄1或2张图像/视频时,会发生此问题.

We're using the UIImagePickerController to do this. The problem occurs when 1 or 2 images / videos are taken with the camera.

当第三次重新进入相​​机屏幕时,一旦捕获了1或2张图像/视频,则图像是静态的并且不会更新.该视图停留在最后捕获的任何内容的最后一帧.

Once 1 or 2 images / videos are captured when the camera screen is re-entered for a third time the image is static and doesn't update. The view is stuck at the last frame of whatever was captured last.

如果按下捕获按钮,则图像/视频突然更新并捕获了相机指向的内容.从那时起,选择器就可以正常进行其他操作了.另外,还会从相机胶卷中选择图片/视频,以使其他图片/视频再次恢复正常.最后,当屏幕没有响应并且用户选择拍照时,视图将缩小为视图内的一个小矩形.控制器的设置如下:

If the capture button is pressed then the image / video suddenly updates and has captured what the camera was pointing at. From then on the picker is good for another go behaving normally. Additionally selecting a picture / video from the camera roll appears to make everything behave again for another picture / video. Finally when the screen isn't responding and the user has selected to take a picture the view will shrink to a small rectangle within the view. The controller is being setup as follows:

    private void SourceChosen(EventHandler<UIImagePickerMediaPickedEventArgs> captureEvent, int buttonIndex, string[] mediaTypes)
    {
        var picker = ConfigurePicker(mediaTypes, captureEvent);

        if (CameraAvailable && buttonIndex == 0)
        {
            picker.SourceType = UIImagePickerControllerSourceType.Camera;
            picker.CameraDevice = UIImagePickerControllerCameraDevice.Rear;
            this.NavigationController.PresentViewController(picker, true, () => { });
        }

        if ((!CameraAvailable && buttonIndex == 0) || (CameraAvailable && buttonIndex == 1))
        {
            picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
            this.NavigationController.PresentViewController(picker, false, () => { });
        }
    }

    private UIImagePickerController ConfigurePicker(string[] mediaTypes, EventHandler<UIImagePickerMediaPickedEventArgs> captureEvent)
    {
        var mediaPicker = new UIImagePickerController();
        mediaPicker.FinishedPickingMedia += captureEvent;
        mediaPicker.Canceled += (sender, args) => mediaPicker.DismissViewController(true, () => { });
        mediaPicker.SetBarDefaults();
        mediaPicker.MediaTypes = mediaTypes;
        return mediaPicker;
    }

captureEvent的示例如下:

An example of a captureEvent is as follows:

    void PhotoChosen(object sender, UIImagePickerMediaPickedEventArgs e)
    {
        UIImage item = e.OriginalImage;
        string fileName = string.Format("{0}.{1}", Guid.NewGuid(), "png");
        string path = Path.Combine(IosConstants.UserPersonalFolder, fileName);
        NSData imageData = item.AsPNG();
        CopyData(imageData, path, fileName, ViewModel.Images, ((UIImagePickerController)sender));
    }

    private void CopyData(NSData imageData, string path, string fileName, List<AssociatedItem> collectionToAddTo, UIImagePickerController picker)
    {
        byte[] imageBytes = new byte[imageData.Length];
        System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, imageBytes, 0, Convert.ToInt32(imageData.Length));
        File.WriteAllBytes(path, imageBytes);

        AssociatedItem item = new AssociatedItem
        {
            StorageKey = fileName
        };

        collectionToAddTo.Add(item);
        picker.DismissViewController(true, ReloadTables);
    }

目前,您可以看到我们没有持有对选择器的引用,但是我们尝试了这段代码的变体,在其中存储了对选择器的引用,并将其放置在CopyData方法之后,我们添加了选择器.释放();在复制数据之后和处理之前(导致随后的选择器在显示时使应用程序崩溃),以及主题上几乎所有其他变体.

At the moment as you can see we're not holding a reference to the picker but we have tried variations of this code where we store a reference to the picker and dispose it after the CopyData method, we've added picker.Release(); after copydata and before the dispose (results in subsequent pickers crashing the application when displayed) and pretty much every other variation on the theme.

有人知道为什么会发生这种情况以及如何解决吗?我以为我们可能内存不足,但不会每次都处置它/仅创建一个实例并将其模式从图片更改为视频会产生任何影响,并且我们始终会看到相同的行为.

Does anyone have any idea why this might be occurring and how to fix it? It was my assumption that we might be running low on memory but neither disposing of it each time / only ever creating one instance and changing its mode from pictures to videos has any affect and we always see the same behaviour.

编辑

感谢Kento,以下内容回答了我们所需的一切,以使它们按预期工作是符合以下条件的:

Thanks to Kento and the below answer what we needed to get it all working as intended was something along the lines of:

public class PickerDelegate : UIImagePickerControllerDelegate
{
    private readonly Action<UIImagePickerController, NSDictionary> _captureEvent;

    public PickerDelegate(Action<UIImagePickerController, NSDictionary> captureEvent)
    {
        _captureEvent = captureEvent;
    }

    public override void FinishedPickingMedia(UIImagePickerController picker, NSDictionary info)
    {
        _captureEvent(picker, info);
    }
}

然后获取图像

    void PhotoChosen(UIImagePickerController picker, NSDictionary info)
    {
        UIImage item = (UIImage)info.ObjectForKey(UIImagePickerController.OriginalImage);
        string fileName = string.Format("{0}.{1}", Guid.NewGuid(), "png");
        string path = Path.Combine(IosConstants.UserPersonalFolder, fileName);
        NSData imageData = item.AsPNG();
        CopyData(imageData, path, fileName, ViewModel.Images, picker);
    }

或获取视频

    void VideoChosen(UIImagePickerController picker, NSDictionary info)
    {
        var videoURL = (NSUrl)info.ObjectForKey(UIImagePickerController.MediaURL);
        NSData videoData = NSData.FromUrl(videoURL);
        string fileName = string.Format("{0}.{1}", Guid.NewGuid(), "mov");
        string path = Path.Combine(IosConstants.UserPersonalFolder, fileName);
        CopyData(videoData, path, fileName, ViewModel.Videos, picker);
    }

推荐答案

我遇到了同样的问题.

此处的帖子未标记为答案,但确实为我解决了问题: https://stackoverflow.com/a/20035698/2514318

The post here is not marked as the answer but it did solve it for me: https://stackoverflow.com/a/20035698/2514318

我猜这是使用FinishedPickingMedia事件时带MonoTouch的错误.我已经读到,使用UIImagePickerController(无论使用obj c还是Mono)都存在泄漏,所以我更喜欢保留实例并重新使用它.如果您确实每次都重新创建它,则建议您处置以前的实例.

I'm guessing this is a bug w/ MonoTouch when using the FinishedPickingMedia event. I have read that there are leaks with using UIImagePickerController (regardless of using obj c or Mono) so I prefer to keep the instance around and re-use it. If you do re-create it each time, I would recommend disposing the previous instance.

Xamarin的任何人都可以参与,如果这是错误的话?

Can anyone from Xamarin weigh in on if this is a bug or not?

这篇关于iOS Monotouch UIImagePickerController来自相机的多张照片/视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆