【Swift/PhotoKit】デバイスに写真を保存・削除・更新する方法!

この記事からわかること

  • PhotoKitとは?
  • デバイス写真保存削除変更する方法
  • performChangesメソッドの使い方
  • performChangesAndWaitとの違い
  • PHAssetChangeRequestクラスとは?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

参考文献:Apple-PhotoKit
参考文献:Fetching Objects and Requesting Changes

PhotoKitとは?

そもそもPhotoKitとはApple製のデバイスに入っている「写真アプリ」で管理されている写真や動画を操作するためのAPIを提供している技術です。実際の中身はPhotos FrameworkとPhotosUI Frameworkの2つのフレームワークに分けられて構成されており、それぞれをimportすることで使用できるようになります。

import Photos
import PhotosUI

Photos

カメラロール(フォトライブラリ)を管理するオブジェクトを提供するPHPhotoLibraryや、実際の画像や動画などのアセットを管理するPHAsset、アセットのコレクション(アルバムなど)を表現するPHAssetCollectionなどといった基本的な写真アプリ操作機能を提供。

PhotosUI

画像のピッカービューを構築するためのPHPickerViewControllerやその構成を定義するPHPickerConfigurationなどUIに関する機能を提供。

またPhotosUIの中にPhotosが含まれているためPhotosUIのみでPhotosの機能も使用できるようになります。

今回はPhotoKitを使用してデバイスに写真を保存・削除・更新する方法をまとめていきます。

前準備:info.plistにキーを追加

PhotoKitを使用してアセットやコレクションの取得、ライブラリの更新など、アプリがPhotoKitの高度な機能を使用するためにはアプリ内からデバイスの写真アプリにアクセスできるように「info.plist」に「NSPhotoLibraryUsageDescription」キーを追加する必要があります。

【Swift UIKit】画像をカメラロールから保存/取得/削除する方法!

immutable(不変)なモデルオブジェクト

そもそもPhotoKitではフォトライブラリ内の画像や動画などを操作しやすいように適したモデルオブジェクト(PHAssetなど)に変換して操作しています。

おすすめ記事:【Swift/PhotoKit】PHAssetとは?モデルオブジェクトの取得と操作方法!

しかしこれらのモデルオブジェクトは読み取り専用のimmutable(不変)であり、取得やUIImageとして表示するだけなら可能ですが操作(削除や変更)することができません

変更を可能にするためには変更要求リクエストを構築して明示的に共有オブジェクト(PHPhotoLibrary)にコミットする必要があります。

performChangesメソッドで変更要求リクエストの構築

公式リファレンス:performChangesメソッド

変更要求リクエストはPHPhotoLibraryクラスのperformChangesメソッドを使用して構築します。

func performChanges(
    _ changeBlock: @escaping () -> Void,
    completionHandler: ((Bool, Error?) -> Void)? = nil
)

例えばアセットをお気に入りに登録する場合は以下のようになります。ここではPHPhotoLibraryインスタンスから呼び出したperformChangesメソッド内でリクエスト(PHAssetChangeRequest)を生成しアセットを更新しているのがポイントです。そしてこの変更は実際にデバイスの写真アプリ内にある対象の画像にも影響します。

PHPhotoLibrary.shared().performChanges {
    let request = PHAssetChangeRequest(for: asset)
    request.isFavorite = !asset.isFavorite
} completionHandler: { success, error in
    print("Finished updating asset. " + (success ? "Success." : error!.localizedDescription))
}

またperformChangesメソッドは非同期で実行されますが同期的に実行されるperformChangesAndWaitメソッドも用意されています。使用方法は基本的に同じです。

公式リファレンス:performChangesAndWait

PHAssetChangeRequestクラス

公式リファレンス:PHAssetChangeRequestクラス

PHAssetChangeRequestperformChanges内で使用するアセットのメタデータの作成、削除、変更、またはコンテンツの編集を要求するクラスです。

プロパティからアセットのメタデータを参照でき、任意の値を格納することで変更できます。

class PHAssetChangeRequest : PHChangeRequest {
  var creationDate: Date? // 作成日時
  var location: CLLocation? // 位置情報
  var isFavorite: Bool // お気に入りマークされているかどうか
  var isHidden: Bool // アセットがコレクションで非表示になっているか
}

アセットの保存(UIImage)

UIImageとして保持しているデータをアセットとして新規で保存する場合はcreationRequestForAssetメソッドを使用します。引数に保存したい画像(UIImage型)を渡します。以下のサンプルはSF-Symbolをフォトライブラリに保存しています。

PHPhotoLibrary.shared().performChanges {            
      PHAssetChangeRequest.creationRequestForAsset(from: UIImage(systemName: "iphone")!)
} completionHandler: { success, error in
    print("Finished updating asset. " + (success ? "Success." : error!.localizedDescription))
}

UIImageから保存したアセットにはメタデータが欠落している可能性があります。元データを同じ情報を保持したアセットを作成したい場合はcreationRequestForAssetFromImageを使用します。

アセットの保存(ファイルパス)

creationRequestForAssetFromImageメソッドは指定したファイルパスからアセットを保存するメソッドです。

PHPhotoLibrary.shared().performChanges {            
    PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: fileURL!))
} completionHandler: { success, error in
    print("Finished updating asset. " + (success ? "Success." : error!.localizedDescription))
}

ファイルパス(URL)として指定できるのはサーバーのURLではなくローカル(デバイス内)のファイルパスのようです。サーバーのURLを指定した場合は以下のようなエラーが発生し保存することができませんでした。

The operation couldn’t be completed. (PHPhotosErrorDomain error -1.)

アセットの削除

アセットを削除するにはdeleteAssetsメソッドを使用します。引数には削除したいアセットを配列形式で指定します。

PHPhotoLibrary.shared().performChanges {
    guard let lastAsset = self.photoAssets.last else{ return }
    PHAssetChangeRequest.deleteAssets(NSArray(array: [lastAsset]))
} completionHandler: { success, error in
    print("Finished updating asset. " + (success ? "Success." : error!.localizedDescription))
}

このメソッドを使用して削除を実行しようとすると以下のような確認アラートが表示されます。

【Swift/PhotoKit】デバイスに写真を保存・削除・更新する方法!

おすすめ記事:【Swift/PhotoKit】画像ファイル名を指定して保存する方法!DCF規格とは?

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index