Udostępnij za pośrednictwem


PhotoKit w środowisku Xamarin.iOS

PhotoKit to struktura, która umożliwia aplikacjom wykonywanie zapytań dotyczących biblioteki obrazów systemowych i tworzenie niestandardowych interfejsów użytkownika w celu wyświetlania i modyfikowania jego zawartości. Zawiera ona szereg klas reprezentujących zasoby obrazów i wideo, a także kolekcje zasobów, takich jak albumy i foldery.

Uprawnienia

Zanim aplikacja będzie mogła uzyskać dostęp do biblioteki zdjęć, zostanie wyświetlone okno dialogowe uprawnień. Musisz podać tekst objaśniający w pliku Info.plist , aby wyjaśnić, jak aplikacja korzysta z biblioteki zdjęć, na przykład:

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

Obiekty modelu

Zestaw PhotoKit reprezentuje te zasoby w obiektach modelu. Obiekty modelu reprezentujące same zdjęcia i filmy wideo są typu PHAsset. Element PHAsset zawiera metadane, takie jak typ nośnika zasobu i jego data utworzenia. PHAssetCollection Podobnie klasy i PHCollectionList zawierają metadane dotyczące kolekcji zasobów i list kolekcji odpowiednio. Kolekcje zasobów to grupy zasobów, takie jak wszystkie zdjęcia i filmy wideo w danym roku. Podobnie listy kolekcji to grupy kolekcji zasobów, takie jak zdjęcia i filmy wideo pogrupowane według roku.

Wykonywanie zapytań dotyczących danych modelu

Zestaw PhotoKit ułatwia wykonywanie zapytań dotyczących danych modelu za pomocą różnych metod pobierania. Aby na przykład pobrać wszystkie obrazy, należy wywołać PHAsset.Fetchmetodę , przekazując typ nośnika PHAssetMediaType.Image .

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

Następnie PHFetchResult wystąpienie będzie zawierać wszystkie PHAsset wystąpienia reprezentujące obrazy. Aby uzyskać same obrazy, należy użyć PHImageManager (lub wersji buforowania), PHCachingImageManageraby wysłać żądanie dotyczące obrazu, wywołując metodę RequestImageForAsset. Na przykład poniższy kod pobiera obraz dla każdego zasobu w obiekcie PHFetchResult , który ma być wyświetlany w komórce widoku kolekcji:

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

Spowoduje to wyświetlenie siatki obrazów, jak pokazano poniżej:

Uruchomiona aplikacja wyświetlająca siatkę obrazów

Zapisywanie zmian w bibliotece zdjęć

W ten sposób można obsługiwać wykonywanie zapytań i odczytywanie danych. Możesz również zapisać zmiany z powrotem do biblioteki. Ponieważ wiele zainteresowanych aplikacji może wchodzić w interakcje z systemową biblioteką zdjęć, można zarejestrować obserwatora, aby otrzymywać powiadomienia o zmianach przy użyciu elementu PhotoLibraryObserver. Następnie po wprowadzeniu zmian aplikacja może odpowiednio zaktualizować. Na przykład poniżej przedstawiono prostą implementację, aby ponownie załadować widok kolekcji powyżej:

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

Aby faktycznie zapisać zmiany z aplikacji, należy utworzyć żądanie zmiany. Każda z klas modelu ma skojarzona klasa żądania zmiany. Aby na przykład zmienić element PHAsset, należy utworzyć element PHAssetChangeRequest. Kroki umożliwiające wykonanie zmian, które są zapisywane z powrotem w bibliotece zdjęć i wysyłane do obserwatorów, takich jak powyższe, to:

  1. Wykonaj operację edycji.
  2. Zapisz przefiltrowane dane obrazu w wystąpieniu PHContentEditingOutput .
  3. Wprowadź żądanie zmiany, aby opublikować zmiany z danych wyjściowych edycji.

Oto przykład, który zapisuje zmianę obrazu, który stosuje filtr Noir obrazu podstawowego:

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

Gdy użytkownik wybierze przycisk, zostanie zastosowany filtr:

Dwa przykłady pokazujące zdjęcie przed i po zastosowaniu filtru

PHPhotoLibraryChangeObserverDzięki funkcji zmiana zostanie odzwierciedlona w widoku kolekcji, gdy użytkownik przejdzie z powrotem:

Widok kolekcji zdjęć przedstawiający zmodyfikowane zdjęcie