iOS Monotouch UIImagePickerController wiele zdjęć / filmów z kamery

Doświadczamy dziwnego problemu z kontrolerem UIImagePickerController. W naszej aplikacji użytkownicy mogą wypełniać szereg formularzy, a także dołączać obrazy i filmy w tych formularzach.

Umożliwiamy użytkownikom dodawanie wielu zdjęć / filmów z rolki aparatu lub przechwytywanie w momencie wypełniania formularza.

W tym celu używamy kontrolera UIImagePickerController. Problem występuje, gdy 1 lub 2 zdjęcia / filmy są zrobione aparatem.

Po zarejestrowaniu 1 lub 2 zdjęć / filmów, gdy ekran aparatu zostanie ponownie wprowadzony po raz trzeci, obraz jest statyczny i nie aktualizuje się. Widok utknął w ostatniej klatce tego, co zostało uchwycone jako ostatnie.

Po naciśnięciu przycisku przechwytywania obraz / wideo nagle się aktualizuje i przechwycił to, do czego skierowany był aparat. Od tej pory selektor jest dobry do kolejnego normalnego zachowania. Dodatkowo wybranie zdjęcia / filmu z rolki kamery powoduje, że wszystko zachowuje się ponownie dla innego zdjęcia / filmu. Wreszcie, gdy ekran nie odpowiada i użytkownik wybrał wykonanie zdjęcia, widok zmniejszy się do małego prostokąta w widoku. Kontroler jest konfigurowany w następujący sposób:

    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;
    }

Przykład zdarzenia przechwytywania jest następujący:

    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);
    }

W tej chwili, jak widać, nie trzymamy odniesienia do selektora, ale wypróbowaliśmy odmiany tego kodu, w którym przechowujemy referencję do selektora i usuwamy go po metodzie CopyData, dodaliśmy picker.Release () ; po kopydacie i przed pozbyciem się (powoduje, że kolejni zbieracze rozbijają aplikację po wyświetleniu) i prawie każda inna odmiana tematu.

Czy ktoś ma jakiś pomysł, dlaczego tak się dzieje i jak to naprawić? To było moje założenie, że może nam brakować pamięci, ale ani pozbycie się jej za każdym razem / tylko stworzenie jednej instancji i zmiana jej trybu ze zdjęć na wideo ma jakikolwiek wpływ i zawsze widzimy to samo zachowanie.

EDYTOWAĆ

Dzięki Kento i poniższej odpowiedzi, wszystko, czego potrzebowaliśmy, aby wszystko działało zgodnie z przeznaczeniem, było czymś w rodzaju:

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);
    }
}

Następnie, aby uzyskać obraz

    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);
    }

Lub uzyskać film

    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);
    }

questionAnswers(2)

yourAnswerToTheQuestion