Capturing and storing a picture with UIImageWriteToSavedPhotosAlbum() - ios

I'm trying to capture and save a picture using the UIImageWriteToSavedPhotosAlbum() funciton. Here is the code I have right now.
#IBAction func CameraAction(sender: UIButton) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .Camera
presentViewController(picker, animated: true, completion:nil)
So essentially I created an object called picker with the UIImagePickerController() class. I want to use the UIImageWriteToSavedPhotosAlbum() function so that I can save the photo that was just taken with the code above to the photo album. I know there are 4 parameters in total that I need to use in order to correctly use the UIImageWriteToSavedPhotosAlbum() function. I figured for the 2nd, 3rd, and 4th parameter I can set it to nil. I'm mainly confused about the first parameter. I know its supposed to be a UIImage. How to I get the picture I just took with the code above as a UIImage?

Add UIImagePickerControllerDelegate delegate tinyour viewcontroller class
Implement the completion method
func imagePickerController(picker:UIImagePickerController!, didFinishPickingMediaWithInfo info:NSDictionary)
{
if(picker.sourceType == UIImagePickerControllerSourceType.Camera)
{
// Access the uncropped image from info dictionary
var imageToSave: UIImage = info.objectForKey(UIImagePickerControllerOriginalImage) as UIImage
UIImageWriteToSavedPhotosAlbum(imageToSave, nil, nil, nil)
self.dismissViewControllerAnimated(true, completion: nil)
}
}

Related

PHPickerViewController's Cancel Button is not working in iOS 15

I am using PHPickerViewController to pick Image for User Profile Picture Purpose in iOS 15. I am using UIKit framework. I have the following code:
var pickerConfig = PHPickerConfiguration(photoLibrary: .shared())
pickerConfig.selectionLimit = 1
pickerConfig.filter = .images
let pickerView = PHPickerViewController(configuration: pickerConfig)
pickerView.delegate = self
self.present(pickerView, animated: true)
The Picker is working properly for selecting images and delegating the results. But, when the Cancel button is pressed, nothing happens and the Picker is not dismissed as expected.
How to dismiss the PHPickerViewController instance when its own Cancel button is pressed ?
Edit:
The implementation of PHPickerViewControllerDelegate Method is as follows:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
{
results.first?.itemProvider.loadObject(ofClass: UIImage.self) { [unowned self] reading , error in
guard let image = reading as? UIImage, error == nil else
{
DispatchQueue.main.async {
picker.dismiss(animated: true)
self.profilePictureHasError = true
self.toggleDoneButtonEnabled()
}
return
}
self.profilePictureHasError = false
DispatchQueue.main.async {
picker.dismiss(animated: true)
self.profilePictureHasChanged = self.userProfilePicture != image
if self.profilePictureHasChanged
{
self.profilePictureView.image = image
self.toggleDoneButtonEnabled()
}
}
}
}
You need to dismiss the picker yourself in the picker(_:didFinishPicking:) delegate method which is called when the user completes a selection or when they tap the cancel button.
From the Apple docs for picker(_:didFinishPicking:):
The system doesn’t automatically dismiss the picker after calling this method.
For example:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// Do something with the results here
picker.dismiss(animated: true)
}
Your current delegate code only calls picker.dismiss when the results array is non-empty (i.e when the user has selected images). When the cancel button is tapped, the delegate method is called with an empty results array.
Fix the issue by adding the following to the top of the code in your delegate method:
if results.isEmpty {
picker.dismiss(animated: true)
return
}
you just wrap it out in an objc func for making cancel button works
#objc
func didOpenPhotos() {
lazy var pickerConfig = PHPickerConfiguration()
pickerConfig.filter = .images
pickerConfig.selectionLimit = 1
let pickerView = PHPickerViewController(configuration: pickerConfig)
pickerView.delegate = self
self.present(pickerView, animated: true)
}
call it anywhere

Xcode Document Picker Delegate in UIKit

Why cant I set the delegate to self? I'm running the code below in the viewcontroller.swift file, but I want to call it in a Render.swift file. I've got a metal scene running of the camera view and want to open the file picker in front of it, but it doesn't seem to be very simple.
#IBAction func importFiles(_ sender: Any) {
let documentPicker = UIDocumentPickerViewController(documentTypes: [kUTTypePlainText as String], in: .import)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = false
present(documentPicker, animated: true, completion: nil)
}
It says Cannot assign value of type 'ViewController' to type 'UIDocumentPickerDelegate
In my Renders.swift file I have a function tied to a button that calls the following:
//open dialog for picker...
let myVC: ViewController = ViewController()
myVC.importFiles()
I'm pretty new to this all.
Why cant I set the delegate to self?
Because the delegate needs to be a UIDocumentPickerDelegate, and self is not a UIDocumentPickerDelegate. You need to declare that it is:
class ViewController : UIViewController, UIDocumentPickerDelegate {
That may precipitate other issues (and I expect it will), but at least you'll get past the point where you are now.

Importing image from photo library into an app in xcode

My app keeps crashing and I don't know why. I'm working on a tabbed application part by part and testing it every time I get a part of it done.
Right now I'm working on trying to import an image from the user's device but I can't seem to get it.
I'm currently using Xcode 10.2.1 and I understand that there has been some changes to the delegate methods and I have changed them. It succeeds in building but whenever I tap that one particular tab where I would like to import an image, it crashes.
class UserImage: UIViewController,UINavigationControllerDelegate, UIImagePickerControllerDelegate {
var imagePickerController : UIImagePickerController!
#IBOutlet var ImageView: UIImageView!
#IBAction func Edit(_ sender: Any) {
imagePickerController.delegate = self
imagePickerController.sourceType = .photoLibrary
present(imagePickerController, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
{
if let image = info[.originalImage] as? UIImage {
ImageView.image = image
} else {
print("Take another")
}
self.dismiss(animated: true, completion: nil)
}
It is crashing because you never actually initialized the UIImagePickerController. Since you marked the imagePickerController as a non optional value, your app is going to crash when you try to reference it but it is still nil. Add this line to the beginning of your Edit function to initialize the variable:
imagePickerController = UIImagePickerController()
Edit: Alternatively, as #rmaddy mentioned, you could just make the controller a local variable of the function. In your example, there is no need to make it a property of the class. Essentially you would just remove the declaration from the top of your class and instead declare it inside the function:
let imagePickerController = UIImagePickerController()

How to not perform query on viewDidAppear once a picture has JUST been selected? [duplicate]

This question already has answers here:
How to do some stuff in viewDidAppear only once?
(9 answers)
Closed 6 years ago.
I have a set up for a picture selection as follows:
#IBOutlet weak var imageHolder: UIImageView!
#IBAction func addImage(_ sender: UIButton) {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.photoLibrary
pickerController.allowsEditing = true
self.present(pickerController, animated: true, completion: nil)
}
var imageSaved = UIImage()
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.dismiss(animated: true, completion: nil)
self.imageHolder.image = image
imageSaved = image
}
Selecting the picker brings up all of the pictures on the simulator, then the user can select them. Once it is selected the view returns to the original view and displays the picture in the imageView. It is not saved, though, until a "Save" button is hit in this view. This all works fine. The save button is merely an action that saves the image file to the DB.
I have the viewDidAppear set up to query the DB and display the image that has been saved as soon as the user moves into that view... this also works well. However, since the viewDidAppear is run multiple times, there becomes an issue when a new image is first selected to replace the old one. The "Save" button deletes the old object and replaces it, so once it has been replaced everything works fine. However, after selecting the image in the picker (and before hitting "Save"... and therefore before that file is in the DB) the view briefly displays the newly selected the image, but the viewDidAppear runs again and sends it back to the image currently in the DB. Its not technically an error, but it is ugly and I would like it to be fixed but I am not sure how.
This is the viewDidAppear code also:
override func viewDidAppear(_ animated: Bool) {
let query = PFQuery(className: "ProfilePictures")
query.whereKey("user", equalTo: (PFUser.current()?.objectId!)! as String)
query.findObjectsInBackground { (objects, error) in
if let objectss = objects{
if objectss.count != 0{
for object in objectss{
let imagePulled = object["ProfilePicture"] as! PFFile
imagePulled.getDataInBackground(block: { (data, error) in
if let downloadedImage = UIImage(data: data!){
self.imageHolder.image = downloadedImage
} else{
print(error)
}
})
}
}
}
}
}
Essentially, how do I get the image to only show the newly selected image in that space between selecting it and hitting save?
You should move your initial query in viewDidLoad(). That only gets called once, so it won't replace your image each time the view appears.
Otherwise, if, for some reason, you need to have it in view did viewDidAppear(), you could use dispatch_once to make sure your query only runs the first time the view appears.
Rough example of using dispatch_once:
var token: dispatch_once_t = 0
dispatch_once(&token) { () -> Void in
// your query goes here
}
If you are using Swift 3, please see this other response on how to get dispatch_once like functionality.

Grabbing song info from MPMediaItemPicker

I am attempting to assign the song title, author, and seconds played of a song to a set of variables. However I am unable to pull any information from the song, what would be the best way to do this as currently my way crashes.
func presentPicker (sender:AnyObject) {
//I have all of this within an IBAction if that matters, I am new to programming in general so sorry if theres any stupid mistakes
let mediaPicker = MPMediaPickerController(mediaTypes: .Music)
mediaPicker.delegate = self
mediaPicker.allowsPickingMultipleItems = false
presentViewController(mediaPicker, animated: true, completion: {println(MPMediaItemCollection())})
}
You shouldn't be using the completion argument of presentViewController:. The completion runs when the controller successfully presents, but you want to grab the song when it's finished dismissing. You need to implement this delegate method in your class:
func mediaPicker(mediaPicker: MPMediaPickerController!,
didPickMediaItems mediaItemCollection: MPMediaItemCollection!) {
println(mediaItemCollection)
}
That method will be called on your class when the user has selected a song because you set delegate equal to self. You may also want to implement this one to find out if they cancelled the picker:
func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController!)

Resources