PhotoKit no Xamarin.iOS
PhotoKit é uma estrutura que permite que os aplicativos consultem a biblioteca de imagens do sistema e criem interfaces de usuário personalizadas para visualizar e modificar seu conteúdo. Ele inclui várias classes que representam ativos de imagem e vídeo, bem como coleções de ativos, como álbuns e pastas.
Permissões
Antes que seu aplicativo possa acessar a biblioteca de fotos, o usuário receberá uma caixa de diálogo de permissões. Você deve fornecer texto explicativo no arquivo Info.plist para explicar como seu aplicativo usa a biblioteca de fotos, por exemplo:
<key>NSPhotoLibraryUsageDescription</key>
<string>Applies filters to photos and updates the original image</string>
Objetos de modelo
O PhotoKit representa esses ativos no que chama de objetos modelo. Os objetos de modelo que representam as próprias fotos e vídeos são do tipo PHAsset
. A PHAsset
contém metadados, como o tipo de mídia do ativo e sua data de criação.
Da mesma forma, as PHAssetCollection
classes e PHCollectionList
contêm metadados sobre coleções de ativos e listas de coleção, respectivamente. As coleções de ativos são grupos de ativos, como todas as fotos e vídeos de um determinado ano. Da mesma forma, listas de coleções são grupos de coleções de ativos, como fotos e vídeos agrupados por ano.
Consultando dados do modelo
O PhotoKit facilita a consulta de dados de modelo por meio de uma variedade de métodos de busca. Por exemplo, para recuperar todas as imagens, você chamaria PHAsset.Fetch
, passando o PHAssetMediaType.Image
tipo de mídia.
PHFetchResult fetchResults = PHAsset.FetchAssets (PHAssetMediaType.Image, null);
A PHFetchResult
instância conteria todas as PHAsset
instâncias que representam imagens. Para obter as imagens em si, use o PHImageManager
(ou a versão de cache, PHCachingImageManager
) para fazer uma solicitação para a imagem chamando RequestImageForAsset
. Por exemplo, o código a seguir recupera uma imagem para cada ativo em um PHFetchResult
para exibir em uma célula de exibição de coleção:
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;
}
Isso resulta em uma grade de imagens como mostrado abaixo:
Salvando alterações na Biblioteca de Fotos
É assim que se lida com a consulta e a leitura de dados. Você também pode gravar alterações de volta na biblioteca. Como vários aplicativos interessados são capazes de interagir com a biblioteca de fotos do sistema, você pode registrar um observador para ser notificado de alterações usando um PhotoLibraryObserver
arquivo . Em seguida, quando as alterações chegam, seu aplicativo pode atualizar de acordo. Por exemplo, aqui está uma implementação simples para recarregar a exibição de coleção acima:
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 ();
});
}
}
Para realmente gravar as alterações de volta do seu aplicativo, você cria uma solicitação de alteração. Cada uma das classes de modelo tem uma classe de solicitação de alteração associada. Por exemplo, para alterar um PHAsset
, crie um PHAssetChangeRequest
arquivo . As etapas para executar alterações que são gravadas de volta na biblioteca de fotos e enviadas a observadores como o acima são:
- Execute a operação de edição.
- Salve os dados de imagem filtrados em uma
PHContentEditingOutput
instância. - Faça uma solicitação de alteração para publicar as alterações da saída de edição.
Aqui está um exemplo que grava uma alteração em uma imagem que aplica um filtro noir de imagem principal:
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));
});
}
Quando o usuário seleciona o botão, o filtro é aplicado:
E graças ao PHPhotoLibraryChangeObserver
, a alteração é refletida na visualização da coleção quando o usuário navega de volta: