PhotoKit в Xamarin.iOS

PhotoKit — это платформа, которая позволяет приложениям запрашивать системную библиотеку изображений и создавать пользовательские пользовательские интерфейсы для просмотра и изменения его содержимого. Он включает в себя ряд классов, представляющих ресурсы изображения и видео, а также коллекции ресурсов, таких как альбомы и папки.

Разрешения

Прежде чем приложение сможет получить доступ к библиотеке фотографий, пользователь получит диалоговое окно разрешений. Чтобы объяснить, как приложение использует библиотеку фотографий, необходимо указать пояснительный текст в файле Info.plist , например:

<key>NSPhotoLibraryUsageDescription</key>
<string>Applies filters to photos and updates the original image</string>

Объекты модели

PhotoKit представляет эти ресурсы в том, что он называет объектами модели. Объекты модели, представляющие фотографии и видео, относятся к типу PHAsset. A PHAsset содержит метаданные, такие как тип носителя ресурса и дата его создания. Аналогичным образом, PHAssetCollectionPHCollectionList классы содержат метаданные о коллекциях активов и списках коллекций соответственно. Коллекции активов — это группы ресурсов, такие как все фотографии и видео за данный год. Аналогичным образом списки коллекций являются группами коллекций активов, таких как фотографии и видео, сгруппированные по годам.

Запрос данных модели

PhotoKit упрощает запрос данных модели с помощью различных методов получения. Например, чтобы получить все изображения, необходимо вызвать PHAsset.Fetch, передав PHAssetMediaType.Image тип носителя.

PHFetchResult fetchResults = PHAsset.FetchAssets (PHAssetMediaType.Image, null);

Затем PHFetchResult экземпляр будет содержать все PHAsset экземпляры, представляющие изображения. Чтобы получить сами изображения, используйте PHImageManager (или версию кэширования), PHCachingImageManagerчтобы запросить изображение путем вызова RequestImageForAsset. Например, следующий код извлекает изображение для каждого ресурса в PHFetchResult ячейке представления коллекции:

public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
    var imageCell = (ImageCell)collectionView.DequeueReusableCell (cellId, indexPath);
    imageMgr.RequestImageForAsset (
        (PHAsset)fetchResults [(uint)indexPath.Item],
        thumbnailSize,
        PHImageContentMode.AspectFill, new PHImageRequestOptions (),
        (img, info) => {
            imageCell.ImageView.Image = img;
        }
    );
    return imageCell;
}

Это приводит к сетке изображений, как показано ниже:

Работающее приложение, отображающее сетку изображений

Сохранение изменений в библиотеке фотографий

Вот как обрабатывать запросы и чтение данных. Вы также можете записать изменения обратно в библиотеку. Так как несколько заинтересованных приложений могут взаимодействовать с системной фототекой, вы можете зарегистрировать наблюдателя, чтобы получать уведомления об изменениях с помощью .PhotoLibraryObserver Затем, когда изменения будут внесены, приложение может соответствующим образом обновиться. Например, вот простая реализация для перезагрузки представления коллекции выше:

class PhotoLibraryObserver : PHPhotoLibraryChangeObserver
{
    readonly PhotosViewController controller;
    public PhotoLibraryObserver (PhotosViewController controller)

    {
        this.controller = controller;
    }

    public override void PhotoLibraryDidChange (PHChange changeInstance)
    {
        DispatchQueue.MainQueue.DispatchAsync (() => {
            var changes = changeInstance.GetFetchResultChangeDetails (controller.fetchResults);
            controller.fetchResults = changes.FetchResultAfterChanges;
            controller.CollectionView.ReloadData ();
        });
    }
}

Чтобы на самом деле записать изменения из приложения, создайте запрос на изменение. Каждый класс модели имеет связанный класс запроса на изменение. Например, чтобы изменить PHAssetобъект, создайте объект PHAssetChangeRequest. Действия по выполнению изменений, которые записываются обратно в фототеку и отправляются наблюдателям, как описано выше:

  1. Выполните операцию редактирования.
  2. Сохраните отфильтрованные данные изображения в PHContentEditingOutput экземпляре.
  3. Внесите запрос на изменение, чтобы опубликовать изменения из выходных данных редактирования.

Ниже приведен пример, который записывает изменения в изображение, которое применяет фильтр noir Core Image:

void ApplyNoirFilter (object sender, EventArgs e)
{
    Asset.RequestContentEditingInput (new PHContentEditingInputRequestOptions (), (input, options) => {

        // perform the editing operation, which applies a noir filter in this case
        var image = CIImage.FromUrl (input.FullSizeImageUrl);
        image = image.CreateWithOrientation((CIImageOrientation)input.FullSizeImageOrientation);
        var noir = new CIPhotoEffectNoir {
            Image = image
        };
        var ciContext = CIContext.FromOptions (null);
        var output = noir.OutputImage;
        var uiImage = UIImage.FromImage (ciContext.CreateCGImage (output, output.Extent));
        imageView.Image = uiImage;
        //
        // save the filtered image data to a PHContentEditingOutput instance
        var editingOutput = new PHContentEditingOutput(input);
        var adjustmentData = new PHAdjustmentData();
        var data = uiImage.AsJPEG();
        NSError error;
        data.Save(editingOutput.RenderedContentUrl, false, out error);
        editingOutput.AdjustmentData = adjustmentData;
        //
        // make a change request to publish the changes form the editing output
        PHPhotoLibrary.GetSharedPhotoLibrary.PerformChanges (() => {
            PHAssetChangeRequest request = PHAssetChangeRequest.ChangeRequest(Asset);
            request.ContentEditingOutput = editingOutput;
        },
        (ok, err) => Console.WriteLine ("photo updated successfully: {0}", ok));
    });
}

Когда пользователь выбирает кнопку, применяется фильтр:

Два примера, показывающие фотографию до и после применения фильтра

И благодаря изменению PHPhotoLibraryChangeObserver, это изменение отражается в представлении коллекции при переходе пользователя обратно:

Представление коллекции фотографий с измененной фотографией