How would I upload new photo into collectionView cell using Firebase? - ios

The code here allows me to upload and download one photo to Firebase and save it to user defaults but I'm trying to figure out how to do it within a collectionView cell and display as many photos wanted, adding on new items
import UIKit
import FirebaseStorage
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
private let storage = Storage.storage().reference()
#IBOutlet var imageView: UIImageView!
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
label.numberOfLines = 0
guard let urlString = UserDefaults.standard.value(forKey: "url") as? String, let url = URL(string: urlString) else {
return
}
label.text = urlString
let task = URLSession.shared.dataTask(with: url, completionHandler: { data,_,error in
guard let data = data, error == nil else {
return
}
DispatchQueue.main.async {
let image = UIImage(data: data)
self.imageView.image = image
}
})
task.resume()
}
#IBAction func didTapButton() {
let picker = UIImagePickerController()
picker.sourceType = .photoLibrary
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else {
return
}
guard let imageData = image.pngData() else {
return
}
storage.child("Images/Photo.png").putData(imageData, metadata: nil) { (_, error) in
guard error == nil else {
print("Failed to Upload Data")
return
}
self.storage.child("Images/Photo.png").downloadURL(completion: {url, error in
guard let url = url, error == nil else {
return
}
let urlString = url.absoluteString
DispatchQueue.main.async {
self.label.text = urlString
self.imageView.image = image
}
print("Download URL: \(urlString)")
UserDefaults.standard.set(urlString, forKey: "url")
})
}
// Upload Image Data
// Get Download URL
// Save Download URL to userDefaults
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}

To upload images to Firebase storage and show them in a collection view, you can use the following steps;
Set up collection view with an array of URLs (or Strings) as its
data source. You can use your custom models if required.
Keep a reference to your Firebase storage and upload the image. After successful upload, get the URL for the uploaded image using the image reference.
Save the url in Firebase Database(or Cloud Firestore). This is required only if you want to sync the collection view with the database and update it when new images are uploaded.
Add a listener to your Firebase database reference where you have
saved the image URLs. Update the local URLs array inside the listener and reload the collection view.
If you don't want to use Firebase database, omit steps 3 and 4, save the image URL to the array and reload the collection view right away.
I'm not adding the code for collection view setup here as it's not the objective of this answer.
let storageRef = Storage.storage().reference(withPath: "images")
let databaseRef = Database.database().reference(withPath:"images")
var images: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
addDatabaseListener()
}
private func addDatabaseListener() {
databaseRef.observe(.childAdded) { (snapshot) in
guard let value = snapshot.value as? [String: Any], let url = value["url"] as? String else { return }
self.images.append(url)
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true)
guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage, let data = image.jpegData(compressionQuality: 0.1) else { return }
let fileName = "\(Date.timeIntervalSinceReferenceDate).jpeg"
let newImageRef = storageRef.child(fileName)
newImageRef.putData(data, metadata: nil) { (_, error) in
if let error = error {
print("upload failed: ", error.localizedDescription)
return
}
newImageRef.downloadURL { (url, error) in
if let error = error {
print("error: ", error.localizedDescription)
return
}
self.databaseRef.childByAutoId().setValue(["url": url?.absoluteString])
}
}
}

Related

How to deselect photo selection after uploading it?

My question is, how can I deselect(or empty the selection) after finishing uploading.
Right now, image upload successfully and display at HomeView as well. But when I try just to click share button it upload again the last selection. How can I fix that?
PhotoPicker:
struct PhotoPicker: UIViewControllerRepresentable {
#Binding var image: UIImage
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.allowsEditing = true
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) { }
func makeCoordinator() -> Coordinator {
return Coordinator(photoPicker: self)
}
final class Coordinator:NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let photoPicker: PhotoPicker
init(photoPicker: PhotoPicker){
self.photoPicker = photoPicker
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.editedImage] as? UIImage {
guard let data = image.jpegData(compressionQuality: 1), let compressedImage = UIImage(data: data) else {
return
}
photoPicker.image = compressedImage
} else {
}
picker.dismiss(animated: true)
}
}
}
Function for persistImage:
func persistUserInformation(){
guard let uid = Auth.auth().currentUser?.uid else
{ return }
let ref = Storage.storage().reference(withPath: uid)
guard let data = self.image.jpegData(compressionQuality: 0.5) else { return }
ref.putData(data, metadata: nil) { metadata, err in
if let err = err {
print("There was an error while putting data \(err) " )
return
}
ref.downloadURL { url, error in
if let error = error {
print("There was an error while downloading the data.")
return
}
print("Successfully uploaded image to storage! \(url?.absoluteString ?? "")")
quoteVM.addAQuote(quote: self.quoteField, imageUrl: url!)
}
}
}
I was expecting to refresh the last selection, and leave it empty until another one.

Error uploading a video to Cloud Storage, but not an image (Swift/Xcode/iOS)

I'm trying to upload a video to Google's Cloud Storage, but hit an error:
BackgroundSession <1EE0DA45-0AA5-45FB-AAB4-1580A53F88A8> error requesting a NSURLSessionUploadTask from background transfer daemon: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 27172 named com.apple.nsurlsessiond was interrupted, but the message was sent over an additional proxy and therefore this proxy has become invalid."
_NSURLErrorFailingURLSessionTaskErrorKey=BackgroundUploadTask <26C123A0-427F-45B9-B7A3-64AEBD19A2AA>.<1>, NSLocalizedDescription=unknown error}
Optional("An unknown error occurred, please check the server response.")
2021-03-01 17:00:28.536123+0000 ForfeitV3.2[72747:1363373] BackgroundSession <1EE0DA45-0AA5-45FB-AAB4-1580A53F88A8> connection to background transfer daemon invalidated
Here's my relevant Swift code:
func timelapsePopup() {
let imagePC = UIImagePickerController()
imagePC.sourceType = .photoLibrary
imagePC.delegate = self
imagePC.sourceType = .savedPhotosAlbum
imagePC.mediaTypes = [String(kUTTypeMovie)]
imagePC.allowsEditing = false
V.timelapse = true
present(imagePC, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if V.timelapse == true { //TIMELAPSE
V.timelapse = false
if let selectedVideo = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
// fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
print("Here's the file URL: ", selectedVideo)
dismiss(animated: true, completion: nil)
brain.submitEvidence(itemIndex: V.indexToBePassed, image: UIImage(), timelapsePath: selectedVideo)
}
myTableView.reloadData()
}
mutating func submitEvidence(itemIndex: Int, image: UIImage, timelapsePath: URL) {
print(timelapsePath.absoluteString)
if timelapsePath.absoluteString != "" {
let item = V.items[itemIndex]
item.timelapseURL = timelapsePath
item.timeSubmitted = getCurrentTime()
item.sentForConfirmation = true
self.saveItem(item: item)
self.addTimelapseToFirestore(item: item)
} else {
let item = V.items[itemIndex]
item.image = image.toString()!
item.timeSubmitted = getCurrentTime()
item.sentForConfirmation = true
self.saveItem(item: item)
self.addToFirestore(item: item)
}
}
func addTimelapseToFirestore(item: Item) {
let storage = Storage.storage()
let data = Data()
let storageRef = storage.reference()
let localFile = item.timelapseURL
let photoRef = storageRef.child("videoOne")
let uploadTask = photoRef.putFile(from: localFile!, metadata: nil) { (metadata, error) in
guard let metadata = metadata else {
print(error?.localizedDescription)
return
}
print("video uploaded")
}
}
The weird thing is that it works when uploading an image. Ie if I change the kUTypeMovie to kUTypeImage, and a few other things to make images work, it uploads that just fine to Cloud Storage. When i switch it back to video, it fails.
All help greatly appreciated - let me know if there's any other info you need!
Cheers,
Josh
Please use the following code which uses UIImagePicker object class to select a video or image in your device and upload it to Firebase ( I have made some changes in your code):
#IBAction func uploadButton(_ sender: Any) {
// Configuration
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
picker.mediaTypes = [kUTTypeImage as String, kUTTypeMovie as String]
// Present the UIImagePicker Controller
present(picker, animated: true, completion: nil)
}
// The didFinishPickingMediaWithInfo let's you select an image/video and let's you decide what to do with it.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if V.timelapse == true { //TIMELAPSE
V.timelapse = false
if let selectedVideo = info[UIImagePickerControllerMediaURL] as? NSURL {
// fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
print("Here's the file URL: ", selectedVideo)
dismiss(animated: true, completion: nil)
brain.submitEvidence(itemIndex: V.indexToBePassed, image: UIImage(), timelapsePath: selectedVideo)
}
myTableView.reloadData()
}
mutating func submitEvidence(itemIndex: Int, image: UIImage, timelapsePath: URL) {
print(timelapsePath.absoluteString)
if timelapsePath.absoluteString != "" {
let item = V.items[itemIndex]
item.timelapseURL = timelapsePath
item.timeSubmitted = getCurrentTime()
item.sentForConfirmation = true
self.saveItem(item: item)
self.addTimelapseToFirestore(item: item)
} else {
let item = V.items[itemIndex]
item.image = image.toString()!
item.timeSubmitted = getCurrentTime()
item.sentForConfirmation = true
self.saveItem(item: item)
self.addToFirestore(item: item)
}
}
func addTimelapseToFirestore(item: Item) {
let storage = Storage.storage()
let data = Data()
let storageRef = storage.reference()
let localFile = item.timelapseURL
let photoRef = storageRef.child("videoOne.mov")
let uploadTask = photoRef.putFile(from: localFile!, metadata: nil) { (metadata, error) in
guard let metadata = metadata else {
print(error?.localizedDescription)
return
}
print("video uploaded")
}
}
Please let me know if it works for you.

Image Picker does not crop the image for me correctly (swift) (firebase)

I have an image picker and after the image got picked, it should get uploaded into my Firebase Storage.
Now I have one problem: Somehow all the images dont get cropped correctly.
Did I misplace some Code, because that's the only thing I could think of, since I already got
picker.allowsEditing = true
The picture gets uploaded correctly, but not how I intended to crop it. The "cropper-window" shows up, but it doesnt get saved as intended.
Here is my code:
import UIKit
import Firebase
class editViewController: UIViewController {
#IBOutlet var pfp: UIImageView!
var fireImage: UIImage? = nil
override func viewDidLoad() {
super.viewDidLoad()
setupPfp()
}
func setupPfp(){
pfp.layer.cornerRadius = pfp.frame.height/2
pfp.clipsToBounds = true
pfp.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(presentPicker))
pfp.addGestureRecognizer(tapGesture)
}
#objc func presentPicker(){
let picker = UIImagePickerController()
picker.sourceType = .photoLibrary
picker.allowsEditing = true
picker.delegate = self
self.present(picker, animated: true, completion: nil)
}
func uploadToFirebase(){
guard let imageSelected = self.fireImage else {
print("Image is nil")
return
}
guard let imageData = imageSelected.jpegData(compressionQuality: 0.5) else {
return
}
let storageRef = Storage.storage().reference(forURL: "gs://lidjd-9dad5.appspot.com")
let storageProfileRef = storageRef.child("profileImages").child(Auth.auth().currentUser!.uid)
let metadata = StorageMetadata()
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
let docRef = db.collection("users").document(userID)
metadata.contentType = "image/jpeg"
storageProfileRef.putData(imageData, metadata: metadata) { (storageMetaData, error) in
if error != nil{
print(error!.localizedDescription)
return
}
storageProfileRef.downloadURL { (url, error) in
if let metaImageUrl = url?.absoluteString{
print(metaImageUrl)
docRef.updateData([
"profileimage": metaImageUrl
]){ err in
if let err = err {
print("Error updating document: \(err)")
} else {
print("Profile Image successfully updated")
}}
}
}
}
}
}
extension editViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let imageSelected = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
fireImage = imageSelected
pfp.image = imageSelected
}
if let imageOriginal = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
fireImage = imageOriginal
pfp.image = imageOriginal
}
picker.dismiss(animated: true, completion: nil)
uploadToFirebase()
}
}
Choose one of them .. in your current code you are always using orignal image
extension editViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let imageSelected = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
fireImage = imageSelected
pfp.image = imageSelected
}
else if let imageOriginal = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
fireImage = imageOriginal
pfp.image = imageOriginal
}
picker.dismiss(animated: true, completion: nil)
uploadToFirebase()
}
}

Photo Uploads to Firebase Database and Storage but doesn't save photo in application

So I have an edit profile page where the user can change their profile picture and cover photo. I have it to where once the users selects their image, they click the saveButton and the photo is uploaded to Firebase Database and Firebase Storage and then the edit profile viewcontroller is dismissed and returns to profile view. Only problem I am having is that although the photo uploads to firebase, it doesn't save the image on the app if I close out and reopen it. I'm not sure what I am missing to make that happen. Here is the code below:
import UIKit
import Foundation
import Firebase
import FirebaseDatabase
class NewEditProfileViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var imageView1: UIImageView!
#IBOutlet weak var imageView2: UIImageView!
var ref = DatabaseReference.init()
var imagePicker = UIImagePickerController()
var imagePicked = 0
var selectedImage1: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
self.ref = Database.database().reference()
self.saveFIRData()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = true
}
#IBAction func chooseImage1(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
imagePicked = (sender as AnyObject).tag
present(imagePicker, animated: true)
}
}
#IBAction func chooseImage2(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){
imagePicked = (sender as AnyObject).tag
present(imagePicker, animated: true)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let pickedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
let pickedImage2 = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
if imagePicked == 1 {
self.imageView1.image = pickedImage
} else if imagePicked == 2 {
self.imageView2.image = pickedImage2
}
dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
}
#IBAction func saveButton(_ sender: Any) {
self.saveFIRData()
self.dismiss(animated: true, completion: nil)
}
#IBAction func backButton(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
#objc func saveFIRData() {
guard let image = imageView1.image else { return }
self.uploadProfileImage(image){ url in
self.saveProfileImage(profileURL: url!){ success in
if success != nil{
print("yes")
}
}
}
}
}
extension NewEditProfileViewController {
func uploadProfileImage(_ image:UIImage, completion: #escaping (_ url: URL?)->()) {
guard let uid = Auth.auth().currentUser?.uid else { return }
let storageRef = Storage.storage().reference().child("users/\(uid)")
let imageData = imageView1.image?.jpegData(compressionQuality: 0.8)
let metaData = StorageMetadata()
metaData.contentType = "image/jpeg"
storageRef.putData(imageData!, metadata: metaData) { (metaData, error) in
if error == nil{
print("success")
storageRef.downloadURL(completion: { (url, error) in
completion(url)
})
}else{
print("error in save image")
completion(nil)
}
}
}
func saveProfileImage(profileURL:URL, completion: #escaping ((_ url: URL?) -> ())){
guard let uid = Auth.auth().currentUser?.uid else { return }
let databaseRef = Database.database().reference().child("users/profilePhotoURL/\(uid)")
let userObject = [
"photoURL": profileURL.absoluteString
] as [String:Any]
self.ref.child("users").child(uid).setValue(userObject)
}
}
As I can see in your code in function
func saveProfileImage(profileURL:URL, completion: #escaping ((_ url: URL?) -> ()))
code to download image is missing you have to update your saveProfileImageto support download & then save to local app directory.
func saveProfileImage(profileURL:URL, completion: #escaping ((_ url: URL?) -> ())){
guard let uid = Auth.auth().currentUser?.uid else { return }
let databaseRef = Storage.storage().reference().child("users/profilePhotoURL/\(uid)")
// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes), Change it according to your need
storageRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
} else {
// Save `data` to your local directory here
let imageFilename = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/" + "\(uid).jpg"
data.write(toFile: imageFilename, atomically: true)
}
}
let userObject = [
"photoURL": profileURL.absoluteString
] as [String:Any]
self.ref.child("users").child(uid).setValue(userObject)
}
}
Refer following sample code taken from Firebase guide Download to local section on file "Download File on iOS" page.
// Create a reference to the file you want to download
let islandRef = storageRef.child("images/island.jpg")
// Create local filesystem URL
let localURL = URL(string: "path/to/image")!
// Download to the local filesystem
let downloadTask = islandRef.write(toFile: localURL) { url, error in
if let error = error {
// Uh-oh, an error occurred!
} else {
// Local file URL for "images/island.jpg" is returned
}
}

Uploading Images from UIImage Picker onto new Firebase (Swift)

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)
}
}

Resources