Xamarin.iOS 中的 PhotoKit

PhotoKit 是一種架構,可讓應用程式查詢系統映像庫,並建立自定義使用者介面來檢視及修改其內容。 它包含一些類別,這些類別代表影像和視訊資產,以及專輯和資料夾等資產集合。

權限

在您的應用程式可以存取相片媒體櫃之前,使用者會看到許可權對話框。 您必須在 Info.plist 檔案中提供說明文字,以說明您的應用程式如何使用相片庫,例如:

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

模型物件

PhotoKit 代表這些資產,其所呼叫的模型物件。 代表相片與影片本身的模型物件類型為 PHAssetPHAsset包含元數據,例如資產的媒體類型和其建立日期。 同樣地, 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 篩選的映射:

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當用戶巡覽回時,變更會反映在集合檢視中:

顯示修改相片的相片集合檢視