0

I am trying to save generated UIImage to Camera Roll.

I have necessary privacy string in Info.plist.

I tried couple of methods;

The error I am facing for PHPhotoLibrary is

Error Domain=com.apple.accounts Code=7 "(null)

The codes I have tried;

UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil);

The other one is;

PHPhotoLibrary.shared().savePhoto(image: image!, albumName: "AlbumName", completion: { (asset) in
            
 if asset != nil
 {
               print("error")
 }
})



func savePhoto(image:UIImage, albumName:String, completion:((PHAsset?)->())? = nil) {
    func save() {
        if let album = PHPhotoLibrary.shared().findAlbum(albumName: albumName) {
            PHPhotoLibrary.shared().saveImage(image: image, album: album, completion: completion)
        } else {
            PHPhotoLibrary.shared().createAlbum(albumName: albumName, completion: { (collection) in
                if let collection = collection {
                    PHPhotoLibrary.shared().saveImage(image: image, album: collection, completion: completion)
                } else {
                    completion?(nil)
                }
            })
        }
    }

    if PHPhotoLibrary.authorizationStatus() == .authorized {
        save()
    } else {
        PHPhotoLibrary.requestAuthorization({ (status) in
            if status == .authorized {
                save()
            }
        })
    }
}

// MARK: - Private

fileprivate func findAlbum(albumName: String) -> PHAssetCollection? {
    let fetchOptions = PHFetchOptions()
    fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
    let fetchResult : PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
    guard let photoAlbum = fetchResult.firstObject else {
        return nil
    }
    return photoAlbum
}

fileprivate func createAlbum(albumName: String, completion: @escaping (PHAssetCollection?)->()) {
    var albumPlaceholder: PHObjectPlaceholder?
    PHPhotoLibrary.shared().performChanges({
        let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
        albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
    }, completionHandler: { success, error in
        if success {
            guard let placeholder = albumPlaceholder else {
                completion(nil)
                return
            }
            let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
            guard let album = fetchResult.firstObject else {
                completion(nil)
                return
            }
            completion(album)
        } else {
            completion(nil)
        }
    })
}

fileprivate func saveImage(image: UIImage, album: PHAssetCollection, completion:((PHAsset?)->())? = nil) {
    var placeholder: PHObjectPlaceholder?
    PHPhotoLibrary.shared().performChanges({
        let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
        guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album),
            let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else { return }
        placeholder = photoPlaceholder
        let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
        albumChangeRequest.addAssets(fastEnumeration)
    }, completionHandler: { success, error in
        guard let placeholder = placeholder else {
            completion?(nil)
            return
        }
        if success {
            let assets:PHFetchResult<PHAsset> =  PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
            let asset:PHAsset? = assets.firstObject
            completion?(asset)
        } else {
            completion?(nil)
        }
    })
}

Could you please help me on figuring out this?

BR,

Erdem

erdemgc
  • 1,701
  • 3
  • 23
  • 43
  • try moving your code out of the save method. Btw **Use the register(_:) method to observe photo library changes before fetching content. After the user grants access to the photo library for your app, Photos sends change messages for any empty fetch results you retrieved beforehand, notifying you that library content for those fetches is now available.** – Leo Dabus Aug 31 '20 at 16:51

1 Answers1

0

I have figured it out.

The problem is I have been creating QR Image that is created with CIFilter is CIImage.

It returns error code = -1

You need to create UIImage from CGImage not CIImage

if let output = filter.outputImage?.transformed(by: transform) {
let context = CIContext()
guard let cgImage = context.createCGImage(output, from: output.extent) else { return nil }
return UIImage(cgImage: cgImage)

}

erdemgc
  • 1,701
  • 3
  • 23
  • 43