I have been having a lot of trouble trying to get my photo picker to pick an image, cast it as a Pffile, then upload it to Parse.
I have currently taped together what I have so I could see it being something simple that I can't see.
The error I get is:
reason: 'PFObject values may not have class: UIImage'
Any Ideas?
#IBAction func selectUser(sender: AnyObject) {
let photoPicker = UIImagePickerController()
photoPicker.delegate = self
photoPicker.sourceType = .PhotoLibrary
self.presentViewController(photoPicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageData = UIImageJPEGRepresentation(image, 0.05)
let imageFile = PFFile(name:"image.jpg", data:imageData!)
picSlot.file = imageFile
let currentUser = PFUser.currentUser()
if currentUser != nil {
PFUser.currentUser()?.setObject(image, forKey: "userPic")
}
self.dismissViewControllerAnimated(false, completion: nil)
}
You should use the following:
if currentUser != nil {
PFUser.currentUser()?.setObject(imageFile, forKey: "userPic")
}
You can't explicitly set the UIImage as a member of the PFObject, but you can set a PFFile as a PFObject's attribute.
Related
I'm using UIImagePickerController to pick image i want path of selected image but I can't get it.
what I'm trying in code:
func handleImg() {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var selectedImageFromPicer : UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage {
selectedImageFromPicer = editedImage
} else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {
selectedImageFromPicer = originalImage
}
if let selectedImage = selectedImageFromPicer {
img.image = selectedImage
}
if let imageURL = info[UIImagePickerControllerReferenceURL] as? URL {
let result = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil)
let asset = result.firstObject
var imgStr = asset?.value(forKey: "filename")
print(imgStr!)
}
dismiss(animated: true, completion: nil)
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("canceled picker")
dismiss(animated: true, completion: nil)
}
}
By above code I can only get the name of image. I want path of image.
If you print the info object you will see all available keys for accessing the values of this dictionary. The image path key is UIImagePickerControllerImageURL
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let imageUrl = info["UIImagePickerControllerImageURL"] as? URL else {
return
}
print(imageUrl.path) // prints the path
picker.dismiss(animated: true, completion: nil)
}
Following code may help you in get the image path.
Code to show UIImagePickerController.
#IBAction func showPicker(_ sender: Any) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerControllerSourceType.savedPhotosAlbum
picker.allowsEditing = false
present(picker, animated: true, completion: nil)
}
Delegate method didFinishPickingMediaWithInfo.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
//Check these values
self.dismiss(animated: true, completion: nil);
}
I am trying to access NSURL return value of imagePickerController, but I have no idea as what to enter for the parameters. Is it even possible to get the NSURL from this method, if not, how else should I go about obtaining a NSURL from imagePickerControlle?, As I have been searching for days.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) -> NSURL {
let theURL: NSURL = (info[UIImagePickerControllerReferenceURL] as! NSURL)
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
profilePicture.image = selectedImage
print("searchthis\(theURL)")
dismiss(animated: true, completion: nil)
return theURL
}
I want to access "theURL" here:
#IBAction func signUpPressed(_ sender: AnyObject) {
let authInfo = AuthInfo()
authInfo.email = emailField.text!
authInfo.firstName = firstField.text!
authInfo.lastName = lastField.text!
authInfo.username = usernameField.text!
authInfo.password = passwordField.text!
authInfo.profilePicture = profilePicture.image
let url = imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo: ).theURL
let container = CKContainer.default()
let privateData = container.privateCloudDatabase
let record = CKRecord(recordType: "Authentication")
record.setValue(authInfo.email, forKey: "email")
record.setValue(authInfo.username, forKey: "username")
record.setValue(authInfo.firstName, forKey: "firstName")
record.setValue(authInfo.lastName, forKey: "lastName")
record.setValue(authInfo.password, forKey: "password")
record.setValue(authInfo.profilePicture, forKey: "profilePicture")
record.setValue(CKAsset(fileURL: ))
privateData.save(record, completionHandler: { record, error in
if error != nil {
print(error)
}
})
}
Thank you!
You have to get the profile image separately and have to save URL and image in global variables.
Like:
//first register your view controller for image picker delegates
#IBAction func profilePickBtnPressed(_ sender: AnyObject) {
let _mediaPicker = UIImagePickerController()
_mediaPicker.delegate = self
_mediaPicker.mediaTypes = ["public.image" as String]
_mediaPicker.allowsEditing = false
_mediaPicker.sourceType = .Camera
self.presentViewController(_mediaPicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
//BTW, this is delegate method of picker controller
globalURL = (info[UIImagePickerControllerReferenceURL] as! NSURL)
globalImage = info[UIImagePickerControllerOriginalImage] as! UIImage
profilePicture.image = selectedImage
print("searchthis\(theURL)")
dismiss(animated: true, completion: nil)
}
Then use these globally saved values in this function:
#IBAction func signUpPressed(_ sender: AnyObject) {
let authInfo = AuthInfo()
...
authInfo.profilePicture = globalImage
let url = globalURL
let container = CKContainer.default()
...
}
I have a UIImagePicker set up within my app that works fine. I would like to upload a profile picture to Firebase when my UIImage picker has been chosen. Here is my function for when a picture has been selected.
//image picker did finish code
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
profilePic.contentMode = .ScaleAspectFill
profilePic.image = chosenImage
profilePic.hidden = false
buttonStack.hidden = true
changeButtonView.hidden = false
self.statusLabel.text = "Here is Your Profile Picture"
dismissViewControllerAnimated(true, completion: nil)
}
The new documentation states that we need to declare a NSURl in order to upload a file. Here is my attempt to find the NSURL of the given file, but it doesn't work. Here is the documentation and a link to it:https://firebase.google.com/docs/storage/ios/upload-files#upload_from_data_in_memory
// File located on disk
let localFile: NSURL = ...
// Create a reference to the file you want to upload
let riversRef = storageRef.child("images/rivers.jpg")
// Upload the file to the path "images/rivers.jpg"
let uploadTask = riversRef.putFile(localFile, metadata: nil) { metadata, error in
if (error != nil) {
// Uh-oh, an error occurred!
} else {
// Metadata contains file metadata such as size, content-type, and download URL.
let downloadURL = metadata!.downloadURL
}
}
Here is my attempt for retrieving the NSURL of the UIImagePicker:
//image picker did finish code
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
//getting the object's url
let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDir = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String;
let photoUrl = NSURL(fileURLWithPath: documentDir)
let localPath = photoUrl.URLByAppendingPathComponent(imageName!)
self.localFile = localPath
profilePic.contentMode = .ScaleAspectFill
profilePic.image = chosenImage
profilePic.hidden = false
buttonStack.hidden = true
changeButtonView.hidden = false
self.statusLabel.text = "Here is Your Profile Picture"
dismissViewControllerAnimated(true, completion: nil)
}
I believe that I am also running into difficulties if the image was taken from the camera instead of the gallery since it is not saved on the device yet. How do I find this image/snapshots's NSURL?
Here is my method to upload and download the user profile photo from firebase storage:
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
userPhoto.image = image
dismissViewControllerAnimated(true, completion: nil)
var data = NSData()
data = UIImageJPEGRepresentation(userPhoto.image!, 0.8)!
// set upload path
let filePath = "\(FIRAuth.auth()!.currentUser!.uid)/\("userPhoto")"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
self.storageRef.child(filePath).putData(data, metadata: metaData){(metaData,error) in
if let error = error {
print(error.localizedDescription)
return
}else{
//store downloadURL
let downloadURL = metaData!.downloadURL()!.absoluteString
//store downloadURL at database
self.databaseRef.child("users").child(FIRAuth.auth()!.currentUser!.uid).updateChildValues(["userPhoto": downloadURL])
}
}
}
I also store the Image URL into firebase database and check if the user has a profile photo or you might get a crash:
//get photo back
databaseRef.child("users").child(userID!).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
// check if user has photo
if snapshot.hasChild("userPhoto"){
// set image locatin
let filePath = "\(userID!)/\("userPhoto")"
// Assuming a < 10MB file, though you can change that
self.storageRef.child(filePath).dataWithMaxSize(10*1024*1024, completion: { (data, error) in
let userPhoto = UIImage(data: data!)
self.userPhoto.image = userPhoto
})
}
})
Simple 2020 example
Don't forget to add pod 'Firebase/Storage' to your podfile, and pod install
Add two delegates to your class
class YourScreen: UIViewController,
UIImagePickerControllerDelegate, UINavigationControllerDelegate {
Storyboard, button, link to ...
#IBAction func tapCameraButton() {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
and then
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let im: UIImage = info[.editedImage] as? UIImage else { return }
guard let d: Data = im.jpegData(compressionQuality: 0.5) else { return }
let md = StorageMetadata()
md.contentType = "image/png"
let ref = Storage.storage().reference().child("someFolder/12345678.jpg")
ref.putData(d, metadata: md) { (metadata, error) in
if error == nil {
ref.downloadURL(completion: { (url, error) in
print("Done, url is \(String(describing: url))")
})
}else{
print("error \(String(describing: error))")
}
}
dismiss(animated: true)
}
But where do you put the image?
At the code,
... .child("someFolder/12345678.jpg")
Almost inevitably,
• as the folder name use the user's id, the chat id, the feed id or a similar concept
• for the name, the only possibility is a uuid
Hence almost always
let f = chatId + "/" + UUID().uuidString + ".jpg"
let ref = Storage.storage().reference().child(f)
Working in Swift 4.2
Here i am doing click on image i have added tapGesture then it open gallery then selected image that upload in Firebase and also i add textField Value Too i hope it helps you Thank You
import UIKit
import Firebase
class ViewController: UIViewController {
#IBOutlet var myImageView: UIImageView!
#IBOutlet var txtText: UITextField!
var ref = DatabaseReference.init()
var imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
self.ref = Database.database().reference()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.openGalleryClick(tapGesture:)))
myImageView.isUserInteractionEnabled = true
myImageView.addGestureRecognizer(tapGestureRecognizer)
myImageView.backgroundColor = UIColor.red
}
#objc func openGalleryClick(tapGesture: UITapGestureRecognizer){
self.setupImagePicker()
}
#IBAction func btnSaveClick(_ sender: UIButton) {
self.saveFIRData()
}
func saveFIRData(){
self.uploadMedia(image: myImageView.image!){ url in
self.saveImage(userName: self.txtText.text!, profileImageURL: url!){ success in
if (success != nil){
self.dismiss(animated: true, completion: nil)
}
}
}
}
func uploadMedia(image :UIImage, completion: #escaping ((_ url: URL?) -> ())) {
let storageRef = Storage.storage().reference().child("myimage.png")
let imgData = self.myImageView.image?.pngData()
let metaData = StorageMetadata()
metaData.contentType = "image/png"
storageRef.putData(imgData!, metadata: metaData) { (metadata, error) in
if error == nil{
storageRef.downloadURL(completion: { (url, error) in
completion(url)
})
}else{
print("error in save image")
completion(nil)
}
}
}
func saveImage(userName:String, profileImageURL: URL , completion: #escaping ((_ url: URL?) -> ())){
let dict = ["name": "Yogesh", "text": txtText.text!, "profileImageURL": profileImageURL.absoluteString] as [String : Any]
self.ref.child("chat").childByAutoId().setValue(dict)
}
}
extension ViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate{
func setupImagePicker(){
if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum){
imagePicker.sourceType = .savedPhotosAlbum
imagePicker.delegate = self
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
myImageView.image = image
picker.dismiss(animated: true, completion: nil)
}
}
I would like to display two images on one viewcontroller selecting them from the camera roll,
I have managed to get to the camera roll to be able to select them but when I select one image it places them in both UIImageViews.
I want to be able to display two different images in the UIImageView.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
//handle media here i.e. do stuff with photo
print("imagePickerController called")
if let chosenImage = info[UIImagePickerControllerEditedImage] {
profileImage.image = chosenImage as? UIImage
let user: PFUser = PFUser.currentUser()!
let profileImageData = UIImageJPEGRepresentation(profileImage.image!, 1)
if (profileImageData != nil)
{
let profileFileObject = PFFile(data: profileImageData!)
user.setObject(profileFileObject!, forKey: "profilePicture")
}
}
Up to here I can select one image and save it to Parse successfully, but when I try and add the other code for the other UIImageView, like this:
if let chosenCoverImage = info[UIImagePickerControllerEditedImage] {
coverImage.image = chosenCoverImage as? UIImage
let coverUser: PFUser = PFUser.currentUser()!
let coverImageData = UIImageJPEGRepresentation(coverImage.image!, 1)
if (coverImageData != nil)
{
let coverFileObject = PFFile(data: coverImageData!)
coverUser.setObject(coverFileObject!, forKey: "coverPicture")
}}
}
That second part of code doesn't seem to work though, basically it shows the same image in both UIImageViews, what I think I need is a second
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
}
But that oviously isn't possible in the same swift file.
Any idea's on how I could achieve this?
Thank you in advance!
Here's my full imagePickerConytoller code:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
//handle media here i.e. do stuff with photo
print("imagePickerController called")
let chosenImage = info[UIImagePickerControllerEditedImage] as? UIImage
profileImage.image = chosenImage
let user: PFUser = PFUser.currentUser()!
let profileImageData = UIImageJPEGRepresentation(profileImage.image!, 1)
if (profileImageData != nil)
{
let profileFileObject = PFFile(data: profileImageData!)
user.setObject(profileFileObject!, forKey: "profilePicture")
}
let chosenCoverImage = info[UIImagePickerControllerEditedImage] as? UIImage
coverImage.image = chosenCoverImage
let coverUser: PFUser = PFUser.currentUser()!
let coverImageData = UIImageJPEGRepresentation(coverImage.image!, 1)
if (coverImageData != nil)
{
let coverFileObject = PFFile(data: coverImageData!)
coverUser.setObject(coverFileObject!, forKey: "coverPicture")
}
activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
activityIndicator.center = self.profileImage.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.White
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
activityIndicator.color = UIColor.grayColor()
user.saveInBackgroundWithBlock { (success:Bool, error:NSError?) -> Void in
self.activityIndicator.stopAnimating()
}
dismissViewControllerAnimated(true, completion: nil)
}
And here is how I get them from Parse in my ViewDidLoad :
if (PFUser.currentUser()?.objectForKey("profilePicture") != nil)
{
let userImageFile:PFFile = PFUser.currentUser()?.objectForKey("profilePicture") as! PFFile
userImageFile.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
self.profileImage.image = UIImage(data: imageData!)
})
}
if (PFUser.currentUser()?.objectForKey("coverPicture") != nil)
{
let userCoverFile:PFFile = PFUser.currentUser()?.objectForKey("coverPicture") as! PFFile
userCoverFile.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
self.coverImage.image = UIImage(data: imageData!)
})
}
this isn't going to be complete, but will have the key parts you will need
class ResponsePhotoController: UIViewController, UIImagePickerControllerDelegate
{
var imageType : Int = 0 // use this to track the image type
// 0 for profile
// 1 for cover
in your code to go get the profile image
imageType = 0
and then when you go get the cover image
imageType = 1
and then in the imagePickerController
if imageType == 0
{
// set up the profile picture
}
else
{
// set up the cover image
}
yo can use use a string "CameraFor" here on camera button click.
set string on profile camera button click "ImageForProfile"
set string on Cover camera button click "ImageForCoverPhoto".
class ResponsePhotoController: UIViewController, UIImagePickerControllerDelegate
{
imageType : Int = 0 // use this to find image type public class variable
if CameraFor == "ImageForProfile" {
//set image here for profile
}
else {
//set image here for ImageForCoverPhoto
}
}
I was trying to set up the sign up page so that the user can set up a profile picture but as soon as i press the sign up button and it segues to the signup page it keeps crashing because of the profile picture codes. This is the button to set the profile picture
#IBAction func setProfilePicture(sender: AnyObject) {
let myPickerController = UIImagePickerController()
myPickerController.delegate = self
myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(myPickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
profilePictureIV.image = info[UIImagePickerControllerOriginalImage] as? UIImage
self.dismissViewControllerAnimated(true, completion: nil)
}
and this is the code to send the data to parse in the viewDidLoad() method
let newUser = PFUser()
let profilePicture = UIImageJPEGRepresentation((profilePictureIV?.image)!, 1)
if(profilePicture != nil) {
let profilePictureImageFile = PFFile(data: profilePicture!)
newUser["profilePicture"] = profilePictureImageFile
}
...
}
The line that keeps crashing is the let profilePicture.... line giving an error:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
The error occurs when profilePictureIV?.image is nil while being unwrapped, so check it
let newUser = PFUser()
if let profilePicture = UIImageJPEGRepresentation(profilePictureIV?.image, 1) {
let profilePictureImageFile = PFFile(data: profilePicture)
newUser["profilePicture"] = profilePictureImageFile
}
or
let newUser = PFUser()
if let profilePictureImage = profilePictureIV?.image {
let profilePicture = UIImageJPEGRepresentation(profilePictureImage, 1)!
let profilePictureImageFile = PFFile(data: profilePicture)
newUser["profilePicture"] = profilePictureImageFile
}