RequestContentEditingInput completionHandler do not run

1.2k Views Asked by At

I have a app where i need to pick images from the phone and display them in the order the user picked them (i need img's in the order picked , not "most recent edited" that is why i am not using UIImagePickerController)

To do this i have a page that shows the latest 50 images with the possibility to load more.

I am getting the Image path and orientation with this code below.

My problem: The CompletionHandler (in RequestContentEditingInput) will only run 17 times... I can see that the the RequestContentEditingInput is called for every image (on this phone 138 times)

I have tried to wait but nothing happens.

The code works as intended when i have less than 17 images...

I have tried to implement a SemaphoreSlim lock in the CompletionHandler code to control that i would only process 10 images at the time but the end result was ether the same or no images was processed at all.

UpdateInfo: It seems its all the LivePhotos that is not processed.

Do anyone have an idea on what is happening here?

An idea for a fix?

Is there another way i can get all image paths and orientation?

Or a totally other solution to let the user pick images from the phone and get the order the user picked them in?

    public class GalleryHelper : IGalleryHelper
    {
        private List<(string, string, string)> _retval;
        private nint _numberofImg = 0;
        private nint _currentImg = 0;

        public List<(string, string, string)> GetAllImgFromGallery()
        {
            _retval = new List<(string, string, string)>();
            _currentImg = 0;
            GetAllImg();
            return _retval;
        }

        private void GetAllImg()
        {
            var fetchOptions = new PHFetchOptions();

            PHFetchResult allPhotos = PHAsset.FetchAssets(PHAssetMediaType.Image, fetchOptions);
            _numberofImg = allPhotos.Count;

            Debug.WriteLine("Total img no + " + _numberofImg);

            for (nint i = 0; i < allPhotos.Count; i++)
            {
                Debug.WriteLine("Starting " + i);
                (allPhotos[i] as PHAsset).RequestContentEditingInput(new PHContentEditingInputRequestOptions(), CompletionHandler);
            }
        }

        private void CompletionHandler(PHContentEditingInput contentEditingInput, NSDictionary requestStatusInfo)
        {
            Debug.WriteLine("Starting CompletionHandler " + (1 + _currentImg));
            var path = contentEditingInput.FullSizeImageUrl.Path;
            if (path != null)
            {
                var orientation = contentEditingInput.FullSizeImageOrientation;

                switch (orientation)
                {
                    case CIImageOrientation.TopLeft:
                        //Standard position
                        _retval.Add((path, null, "0"));
                        break;

                    case CIImageOrientation.LeftBottom:
                        //Rotate 90 degrees clockwise
                        _retval.Add((path, null, "-90"));
                        break;

                    case CIImageOrientation.RightTop:
                        //Rotate 90 degrees counterclockwise
                        _retval.Add((path, null, "90"));
                        break;

                    case CIImageOrientation.BottomRight:
                        //Rotate 180 degrees
                        _retval.Add((path, null, "180"));
                        break;

                    case CIImageOrientation.BottomLeft:
                        //Mirror image rotated 180 degrees
                        _retval.Add((path, null, "180"));
                        break;

                    case CIImageOrientation.TopRight:
                        //Mirror image
                        _retval.Add((path, null, "0"));
                        break;

                    case CIImageOrientation.LeftTop:
                        //Mirror image rotate 90 degrees clockwise
                        _retval.Add((path, null, "-90"));
                        break;

                    case CIImageOrientation.RightBottom:
                        //Mirror image rotate 90 degrees counterclockwise.
                        _retval.Add((path, null, "90"));
                        break;

                    default:
                        _retval.Add((path, null, "0"));
                        break;
                }
            }
            _currentImg++;
            Debug.WriteLine("Images done " + _currentImg);
            MessagingCenter.Send((App)Xamarin.Forms.Application.Current, "ImagesReady", _retval);

        }
    }

A paste from my Debug Output on a run:

[0:] Total img no + 138
[0:] Starting 0
[0:] Starting 1
(...)
[0:] Starting 137
[0:] Starting CompletionHandler 1
[0:] Images done 1
[0:] Starting CompletionHandler 2
[0:] Images done 2
[0:] Starting CompletionHandler 3
[0:] Images done 3
(...)
[0:] Starting CompletionHandler 15
[0:] Images done 15
[0:] Starting CompletionHandler 16
[0:] Images done 16
[0:] Starting CompletionHandler 17
[0:] Images done 17
Thread started: #17
Thread finished: #15
The thread 0xf has exited with code 0 (0x0).
Thread finished: #3
1

There are 1 best solutions below

2
rrr On BEST ANSWER

If anyone in the future has the same problem. Use PHImageManager.DefaultManager.RequestImageData() instead of PHAsset.RequestContentEditingInput() as it do not crash if you ask it to process alot of images.

I do something like:

    var fetchOptions = new PHFetchOptions();
    PHFetchResult allPhotos = PHAsset.FetchAssets(PHAssetMediaType.Image, fetchOptions);
    _numberofImg = allPhotos.Count;
    Debug.WriteLine("Total img no + " + _numberofImg);
    await Task.Yield();
    await Task.Run(() => ImgProcess(allPhotos));
    return true;

private void ImgProcess(PHFetchResult allPhotos)
{
    //await Task.Run(() =>
    //{
        for (nint i = 0; i < allPhotos.Count; i++)
        {
            Debug.WriteLine("Starting " + i);
            var phasset = allPhotos[i] as PHAsset;
            var options = new PHImageRequestOptions()
            {
                Synchronous = true,
                NetworkAccessAllowed = false,
                DeliveryMode = PHImageRequestOptionsDeliveryMode.FastFormat
            };
            PHImageManager.DefaultManager.RequestImageData(phasset, options, ComplManager);
        }
    //});
    //return;
}

even if this solution still have problems when the number of images get over something like 300...