Swift PHAsset PHAssetChangeRequest add/delete Keywords

566 views Asked by At

I would like to programmatically add/delete keywords from Photos in the Photos Library in an iOS app. I have written and tested the code below to toggle the favorite setting on a given photo but I have not been able to find anything in the documentation about the keywords. Photos clearly have metadata that contains keywords.

Here's the simple function to toggle "favorite" on the latest photo in the library and this code does complete as expected.

class ViewController: UIViewController {
    @IBOutlet weak var myImageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        photoAuthorization()
        toggleFavorite()
    }

    private func loadImage() -> UIImage? {

        let manager = PHImageManager.default()
        let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions())

        var image: UIImage? = nil
        manager.requestImage(for: fetchResult.object(at: 0), targetSize: CGSize(width: 800, height: 600), contentMode: .aspectFill, options: requestOptions() ) {img, err in
            guard let img = img else { return }
            image = img
        }
        return image

    }//load Image

    private func fetchOptions() -> PHFetchOptions {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        return fetchOptions
    }//fetch options

    private func requestOptions() -> PHImageRequestOptions {
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = true
        requestOptions.deliveryMode = .highQualityFormat
        return requestOptions
    }//request options

    private func photoAuthorization() {
        let status = PHPhotoLibrary.authorizationStatus()

        switch status {
        case .authorized:
            myImageView.image = loadImage()
        case .restricted, .denied:
            print("put up alert for auth restricted or denied")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization { (status) in
                switch status {
                case .authorized:
                    DispatchQueue.main.async {
                        self.myImageView.image = self.loadImage()
                    }
                case .restricted, .denied:
                    print("in notDetermined put up alert for auth restricted or denied")
                case .notDetermined:
                    break
                @unknown default:
                    fatalError("fatal error inside request authorization (inner loop)")
                }
            }
        @unknown default:
            fatalError("fatal error authorized switch (outer loop)")
        }
    }//photo authorization

    private func toggleFavorite() {

        let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: fetchOptions())
        guard let firstAsset = fetchResult.firstObject else { return }

        PHPhotoLibrary.shared().performChanges({
            let changeRequest = PHAssetChangeRequest(for: firstAsset)
            changeRequest.isFavorite = !firstAsset.isFavorite

            //want to add keyword instead of toggling favorite
            //changeRequest.setValue("jumping", forKey: "keywords")
            //
        }) { (success, error) in
            print(success ? "Successfully updated favorite" : "\(error ?? "error did not work either" as! Error)")
        }
    }//toggle favorite

}//class

Any guidance would be appreciated. Xcode 11.4.1

0

There are 0 answers