Xamarin.iOS の PhotoKit
PhotoKit は、アプリケーションでシステム イメージ ライブラリのクエリを実行し、その内容を表示および変更するカスタム ユーザー インターフェイスを作成できるようにする新しいフレームワークです。 これには、画像や動画の資産だけでなく、アルバムやフォルダーなどの資産のコレクションを表す多くのクラスが含まれています。
アプリが写真ライブラリにアクセスできるようになる前に、ユーザーにアクセス許可ダイアログが表示されます。 Info.plist ファイルには、アプリで写真ライブラリを使用する方法などを説明するテキストを用意する必要があります。これには、次のようなものがあります。
<key>NSPhotoLibraryUsageDescription</key>
<string>Applies filters to photos and updates the original image</string>
PhotoKit は、モデル オブジェクトと呼ばれるものの中でこれらの資産を表します。 写真や動画自体を表すモデル オブジェクトは PHAsset
型です。 PHAsset
には、資産のメディアの種類や作成日などのメタデータが含まれます。
同様に、PHAssetCollection
クラスと PHCollectionList
クラスには、それぞれ資産コレクションとコレクション リストに関するメタデータが含まれています。 資産コレクションは、特定の年のすべての写真や動画などの資産のグループです。 同様に、コレクション リストは、年ごとにグループ化された写真や動画などの資産コレクションのグループです。
PhotoKit を使用すると、さまざまなフェッチ メソッドを通じてモデル データのクエリを簡単に実行できます。 たとえば、すべてのイメージを取得するには、PHAssetMediaType.Image
メディアの種類を渡す PHAsset.Fetch
を呼び出します。
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
インスタンスに保存します。 - 編集出力から変更を公開するために変更要求を行います。
Core Image noir フィルターを適用するイメージに変更を書き戻す例を次に示します。
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
により、ユーザーが戻ると、コレクション ビューに変更が反映されます。