我们遇到了UIImagePickerController的一个奇怪问题。在我们的应用程序中,用户可以填写一系列表格,并附上这些表格中的图像和视频。
我们允许用户从相机胶卷中添加多张照片/视频,或者在填写表格时进行拍摄。
我们正在使用UIImagePickerController来执行此操作。使用相机拍摄1或2张图像/视频时会出现问题。
当第三次重新进入相机屏幕时,一旦拍摄了1或2张图像/视频,图像就会静止并且不会更新。视图停留在最后捕获的任何内容的最后一帧。
如果按下捕获按钮,图像/视频会突然更新并捕获相机指向的内容。从那时起,选择器对于另一个正常行为是好的。此外,从相机胶卷中选择一张照片/视频似乎可以使所有内容再次显示另一张照片/视频。最后,当屏幕没有响应并且用户选择拍照时,视图将缩小为视图内的小矩形。控制器的设置如下:
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的示例如下:
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方法之后处理它,我们添加了选择器。发布();在copydata之后和处置之前(导致随后的选择器在显示时崩溃应用程序)以及主题上几乎所有其他变体。
有谁知道为什么会发生这种情况以及如何解决这个问题?我的假设是我们可能在内存上运行不足但是每次都没有处理它/只创建一个实例并且从图片到视频改变它的模式有任何影响,我们总是看到相同的行为。
修改
感谢Kento以及以下回答我们需要让所有工作按预期工作的内容如下:
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);
}
答案 0 :(得分:5)
我有同样的问题。
这里的帖子没有标记为答案,但确实为我解决了这个问题:https://stackoverflow.com/a/20035698/2514318
我猜这是使用FinishedPickingMedia事件时MonoTouch的错误。我已经读过使用UIImagePickerController存在泄漏(无论使用obj c还是Mono)所以我更喜欢保留实例并重新使用它。如果你每次都重新创建它,我会建议处理前一个实例。
如果这是一个错误,Xamarin的任何人都可以权衡吗?
答案 1 :(得分:2)
这篇文章给了我很多帮助,所以我决定制作一个非常简单的样本并在github上发布给任何可能需要它的人:https://github.com/GiusepeCasagrande/XamarinSimpleCameraSample