Error When Trying to Save a Captured Image in Swift

Error when trying to save a captured image in swift

The problem is that you have never given self.assetCollection or self.photoAsset any value, so they are nil. Thus, when you try to use them in your PHAssetCollectionChangeRequest initializer, you crash.

By the way, if all you want to do is save the image into the camera roll, you don't need all that code. The creation request alone is all you need.

Or, if you want to save the image into the camera roll and into an album, you don't need to call PHAssetCollectionChangeRequest(forAssetCollection:assets:) to do it.

Finally, you really shouldn't have all that extra stuff in the change block. Just do the change and no more. The other stuff should be in the completion block.

Take a photo and save to photo library in Swift

Use below code for an image taken from Photo Gallery and save inside photo library.

Code Support for Swift 3.1 & 4.0 version:

First, we have to do the setup for Permissions inside Project's .plist file:-

1) Camera

<key>NSCameraUsageDescription</key>
<string>This app will use camera.</string>

2) Photo Library

<key>NSPhotoLibraryUsageDescription</key>
<string>You can select photos to attach to reports.</string>

3) Save to Photo Library

<key>NSPhotoLibraryAddUsageDescription</key>
<string>Please allow access to save photo in your photo library</string>

We need to open .pilst file as a Source code type then add permissions inside -

open .plist file


After That


import UIKit

class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

@IBOutlet weak var imageTake: UIImageView!

var imagePicker: UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
}

//MARK: - Take image
@IBAction func takePhoto(_ sender: UIButton) {
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
present(imagePicker, animated: true, completion: nil)
}

//MARK: - Saving Image here
@IBAction func save(_ sender: AnyObject) {
UIImageWriteToSavedPhotosAlbum(imageTake.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

//MARK: - Add image to Library
func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}

//MARK: - Done image capture here
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
imagePicker.dismiss(animated: true, completion: nil)
imageTake.image = info[UIImagePickerControllerOriginalImage] as? UIImage
}

}

Swift 4.2 Code update -

 class ViewController: UIViewController, UINavigationControllerDelegate  {

@IBOutlet weak var imageTake: UIImageView!
var imagePicker: UIImagePickerController!

enum ImageSource {
case photoLibrary
case camera
}

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

//MARK: - Take image
@IBAction func takePhoto(_ sender: UIButton) {
guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
selectImageFrom(.photoLibrary)
return
}
selectImageFrom(.camera)
}

func selectImageFrom(_ source: ImageSource){
imagePicker = UIImagePickerController()
imagePicker.delegate = self
switch source {
case .camera:
imagePicker.sourceType = .camera
case .photoLibrary:
imagePicker.sourceType = .photoLibrary
}
present(imagePicker, animated: true, completion: nil)
}

//MARK: - Saving Image here
@IBAction func save(_ sender: AnyObject) {
guard let selectedImage = imageTake.image else {
print("Image not found!")
return
}
UIImageWriteToSavedPhotosAlbum(selectedImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

//MARK: - Add image to Library
@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
showAlertWith(title: "Save error", message: error.localizedDescription)
} else {
showAlertWith(title: "Saved!", message: "Your image has been saved to your photos.")
}
}

func showAlertWith(title: String, message: String){
let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}

extension ViewController: UIImagePickerControllerDelegate{

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
imagePicker.dismiss(animated: true, completion: nil)
guard let selectedImage = info[.originalImage] as? UIImage else {
print("Image not found!")
return
}
imageTake.image = selectedImage
}
}

Error Saving Image to Photo Library iOS/Mac Catalyst App Swift

I was able to save the images to MacOS through this Mac Catalyst App using the following code in Swift;

func insertImageMac(image : UIImage, albumName : String) {
let collection = fetchAssetCollectionWithAlbumName(albumName: albumName)
if collection == nil {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
}, completionHandler: {(success, error) in
if error != nil {
print("Error: " + error!.localizedDescription)
}

if success {
let newCollection = self.fetchAssetCollectionWithAlbumName(albumName: albumName)
self.insertImage(image: image, intoAssetCollection: newCollection!)
}
}
)
} else {
self.insertImage(image: image, intoAssetCollection: collection!)
}
}

func fetchAssetCollectionWithAlbumName(albumName : String) -> PHAssetCollection? {

let fetchOption = PHFetchOptions()
fetchOption.predicate = NSPredicate(format: "title == '" + albumName + "'")

let fetchResult = PHAssetCollection.fetchAssetCollections(
with: PHAssetCollectionType.album,
subtype: PHAssetCollectionSubtype.albumRegular,
options: fetchOption)
let collection = fetchResult.firstObject as? PHAssetCollection

return collection
}

func insertImage(image : UIImage, intoAssetCollection collection : PHAssetCollection) {
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetCreationRequest.creationRequestForAsset(from: image)
let request = PHAssetCollectionChangeRequest(for: collection)
if request != nil && creationRequest.placeholderForCreatedAsset != nil {
request!.addAssets([creationRequest.placeholderForCreatedAsset!] as NSFastEnumeration)
}

},

completionHandler: { (success, error) in
if error != nil {
print("Error: " + error!.localizedDescription)
let ac = UIAlertController(title: "Save error", message: error!.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Done", style: .default))
self.present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Save success", message: "Image saved", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "Done", style: .default))
self.present(ac, animated: true)
}
}
)
}

...and calling it inside my button function with the image;

insertImageMac(image: myImage, albumName: "AlbumName")

UIImage not saving to Camera Roll

I was able to solve the issue using this code:

@IBAction func SaveTapped(sender: AnyObject) {
let softwareContext = CIContext(options: [kCIContextUseSoftwareRenderer:true])
let cgimg = softwareContext.createCGImage(savedImage,
fromRect: savedImage.extent())

let libary = ALAssetsLibrary()
libary.writeImageToSavedPhotosAlbum(cgimg, metadata: savedImage.properties(),
completionBlock: nil)
}


Related Topics



Leave a reply



Submit