Xamarin.iOS의 PhotoKit

Download Sample 코드 샘플 다운로드

PhotoKit는 애플리케이션이 시스템 이미지 라이브러리를 쿼리하고 사용자 지정 사용자 인터페이스를 만들어 콘텐츠를 보고 수정할 수 있는 프레임워크입니다. 여기에는 이미지 및 비디오 자산을 나타내는 다양한 클래스와 앨범 및 폴더와 같은 자산 컬렉션이 포함됩니다.

사용 권한

앱이 사진 라이브러리에 액세스하기 전에 사용자에게 사용 권한 대화 상자가 표시됩니다. 예를 들어 앱에서 사진 라이브러리를 사용하는 방법을 설명하려면 Info.plist 파일에 설명 텍스트를 제공해야 합니다.

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

모델 개체

PhotoKit는 모델 개체라고 하는 자산에서 이러한 자산을 나타냅니다. 사진 및 비디오 자체를 나타내는 모델 개체는 형식 PHAsset입니다. A PHAsset 는 자산의 미디어 유형 및 해당 생성 날짜와 같은 메타데이터를 포함합니다. 마찬가지로, PHAssetCollection 클래스 및 PHCollectionList 클래스는 각각 자산 컬렉션 및 컬렉션 목록에 대한 메타데이터를 포함합니다. 자산 컬렉션은 지정된 1년 동안의 모든 사진 및 비디오와 같은 자산 그룹입니다. 마찬가지로 컬렉션 목록은 연도별로 그룹화된 사진 및 비디오와 같은 자산 컬렉션 그룹입니다.

모델 데이터 쿼리

PhotoKit을 사용하면 다양한 인출 방법을 통해 모델 데이터를 쉽게 쿼리할 수 있습니다. 예를 들어 모든 이미지를 검색하려면 미디어 형식을 전달하여 호출 PHAsset.Fetch합니다 PHAssetMediaType.Image .

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

그러면 인스턴스에 PHFetchResult 이미지를 나타내는 모든 PHAsset 인스턴스가 포함됩니다. 이미지 자체를 가져오기 위해 (또는 캐싱 버전PHCachingImageManager)를 사용하여 PHImageManager 호출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;
}

그러면 아래와 같이 이미지 그리드가 생성됩니다.

The running app displaying a grid of images

사진 라이브러리에 변경 내용 저장

데이터 쿼리 및 읽기를 처리하는 방법입니다. 변경 내용을 라이브러리에 다시 쓸 수도 있습니다. 여러 관심 있는 애플리케이션이 시스템 사진 라이브러리와 상호 작용할 수 있으므로 관찰자를 등록하여 변경 내용을 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. 편집 출력의 변경 내용을 게시하도록 변경 요청을 합니다.

핵심 이미지 느와르 필터를 적용하는 이미지에 변경 내용을 다시 기록하는 예제는 다음과 같습니다.

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));
    });
}

사용자가 단추를 선택하면 필터가 적용됩니다.

Two examples, showing the photo before and after the filter is applied

PHPhotoLibraryChangeObserver또한 사용자가 다시 탐색할 때 변경 내용이 컬렉션 보기에 반영됩니다.

Photo collection view showing the modified photo