Phones.frameworkを使って、端末の写真の取得・保存・削除を試してみました。
写真を操作する前にInfo.plistにNSPhotoLibraryUsageDescriptionに写真を操作する理由を記述します。
これがないとアプリがクラッシュします。
取得
端末写真をUIImageとして取得する処理は下の通りです。
PHAsset.fetchAssets
でPHAssetを取得、PHImageManagerと取得したPHAssetを使ってUIImageを読み込んでいます。
import UIKit import Photos class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let options = PHFetchOptions() let result = PHAsset.fetchAssets(with: .image, options: options) if let asset = result.firstObject { PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width: asset.pixelWidth, height: asset.pixelHeight), contentMode: .aspectFill, options: nil, resultHandler: { image, options in let imageView = UIImageView(image: image) imageView.frame.origin.x = (self.view.frame.width - imageView.frame.width) / 2 self.view.addSubview(imageView) }) } } }
起動すると写真が表示されていることが分かります。
fetchAssetsの戻り値は下のようなメソッドを持っています。
let result = PHAsset.fetchAssets(with: .image, options: PHFetchOptions()) result.count // → 件数 result.object(at: 0) // → 0番目の要素(PHAsset) result.objects(at: [0, 1, 2]) // → 0, 1, 2番目の要素の配列 result.countOfAssets(with: .audio) // → audioアセットの数を取得
取得の際はソート・NSPredicateを使った絞り込み・取得件数の指定も可能です。
let options = PHFetchOptions() options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: false) ] options.predicate = NSPredicate(format: "pixelWidth < 2000") options.fetchLimit = 1 let result = PHAsset.fetchAssets(with: .image, options: options)
削除
削除処理は下の通りです。
PHAssetChangeRequestのdeleteAssetsメソッドにPHAssetを渡す事で削除します。
if !asset.canPerform(.delete) { return } PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.deleteAssets(NSArray(array: [asset])) }, completionHandler: { _, _ in // 削除後の処理 })
削除の前に、自動で下のダイアログが表示されます。
PHAssetChangeRequestのdeleteAssetsですが、performChangesメソッドを使わずに呼び出すと下のようなエラーになります。
// 単独で呼ぶと下のようなエラー PHAssetChangeRequest.deleteAssets(NSArray(array: [asset])) // 'NSInternalInconsistencyException', reason: 'This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]'
保存
保存は下の通りです。
PHAssetChangeRequestのcreationRequestForAssetにUIImageを渡す事で端末への保存ができます。
let image = UIImage() PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAsset(from: image) }, completionHandler: { _, _ in // 作成後の処理 })