PhotoKit в Xamarin.iOS
PhotoKit — это платформа, которая позволяет приложениям запрашивать системную библиотеку изображений и создавать пользовательские пользовательские интерфейсы для просмотра и изменения его содержимого. Он включает в себя ряд классов, представляющих ресурсы изображения и видео, а также коллекции ресурсов, таких как альбомы и папки.
Разрешения
Прежде чем приложение сможет получить доступ к библиотеке фотографий, пользователь получит диалоговое окно разрешений. Чтобы объяснить, как приложение использует библиотеку фотографий, необходимо указать пояснительный текст в файле Info.plist , например:
<key>NSPhotoLibraryUsageDescription</key>
<string>Applies filters to photos and updates the original image</string>
Объекты модели
PhotoKit представляет эти ресурсы в том, что он называет объектами модели. Объекты модели, представляющие фотографии и видео, относятся к типу PHAsset
. A PHAsset
содержит метаданные, такие как тип носителя ресурса и дата его создания.
Аналогичным образом, PHAssetCollection
PHCollectionList
классы содержат метаданные о коллекциях активов и списках коллекций соответственно. Коллекции активов — это группы ресурсов, такие как все фотографии и видео за данный год. Аналогичным образом списки коллекций являются группами коллекций активов, таких как фотографии и видео, сгруппированные по годам.
Запрос данных модели
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
. Действия по выполнению изменений, которые записываются обратно в фототеку и отправляются наблюдателям, как описано выше:
- Выполните операцию редактирования.
- Сохраните отфильтрованные данные изображения в
PHContentEditingOutput
экземпляре. - Внесите запрос на изменение, чтобы опубликовать изменения из выходных данных редактирования.
Ниже приведен пример, который записывает изменения в изображение, которое применяет фильтр 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
, это изменение отражается в представлении коллекции при переходе пользователя обратно: