0

I have been looking online everywhere to help me out here but I cannot figure this out. The code below says that allows for the image to get stored in the firebase database when the user registers:

func uploadProfileImage(_ image: UIImage, completion: @escaping ((_ url: URL?)->())){
    guard let uid = Auth.auth().currentUser?.uid else {return}
    let storageRef = Storage.storage().reference().child("user/\(uid)")

    guard let imageData = image.jpegData(compressionQuality: 0.75 ) else {return}
    let metaData = StorageMetadata()
    metaData.contentType = "image/jpg."


    storageRef.putData(imageData, metadata: metaData) { metaData, error in
        if error == nil, metaData != nil {
            storageRef.downloadURL { url, error in
                completion(url)
                // success!
            }
        } else {
            // failed
            completion(nil)
        }
    }
}

func saveProfile(name: String, email: String, profileImageURL: URL, completion: @escaping ((_ success:Bool)->())){
    guard let uid = Auth.auth().currentUser?.uid else {return}

    let databaseRef = Database.database().reference().child("users/profile/\(uid)")


    let userObject = ["name":name, "email":email,
                      "photoURL":profileImageURL.absoluteString] as [String:Any]

    databaseRef.setValue(userObject) {error, ref in completion(error == nil)}
    }
}

This code in a different .swift file allows me to get the photo:

static let cache = NSCache<NSString, UIImage>()

static func downloadImage(withURL url:URL, completion: @escaping (_ image:UIImage?, _ url:URL)->()) {
    let dataTask = URLSession.shared.dataTask(with: url) { data, responseURL, error in
        var downloadedImage:UIImage?

        if let data = data {
            downloadedImage = UIImage(data: data)
        }

        if downloadedImage != nil {
            cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString)
        }

        DispatchQueue.main.async {
            completion(downloadedImage, url)
        }

    }

    dataTask.resume()
}

static func getImage(withURL url:URL, completion: @escaping (_ image:UIImage?, _ url:URL)->()) {
    if let image = cache.object(forKey: url.absoluteString as NSString) {
        completion(image, url)
    } else {
        downloadImage(withURL: url, completion: completion)
    }
}

user profile code:

class UserProfile {

var uid:String
var name:String
var photoURL:URL

init(uid:String, name:String, photoURL:URL){

    self.uid = uid
    self.name = name
    self.photoURL = photoURL



}

}

I have added a file that will allow me to get the data from firebase:

class ImageServices{

static let cache = NSCache<NSString, UIImage>()

static func downloadImage(withURL url:URL, completion: @escaping (_ image:UIImage?, _ url:URL)->()) {
    let dataTask = URLSession.shared.dataTask(with: url) { data, responseURL, error in
        var downloadedImage:UIImage?

        if let data = data {
            downloadedImage = UIImage(data: data)
        }

        if downloadedImage != nil {
            cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString)
        }

        DispatchQueue.main.async {
            completion(downloadedImage, url)
        }

    }

    dataTask.resume()
}

static func getImage(withURL url:URL, completion: @escaping (_ image:UIImage?, _ url:URL)->()) {
    if let image = cache.object(forKey: url.absoluteString as NSString) {
        completion(image, url)
    } else {
        downloadImage(withURL: url, completion: completion)
    }
}

}

Now how do I use this in my viewController to actually show the image on the imageView???

  • The question is unclear. viewControllers don't have a profile page so maybe that's something you added to *your* viewController? Also, are you asking about the `.photoUrl` property of a Firebase user object? Or are you asking how to read the node */photoURL* node from your Firebase? If you're trying to read the value of Firebase node, that's covered in the Getting Started Guide [Read Data](https://firebase.google.com/docs/database/ios/read-and-write). I would suggest reviewing that, then clarify and update your question. – Jay May 08 '20 at 17:25
  • What I am asking is how can I get the image from the current logged in user and attach it to an image in a different view controller that I have named my profile page. – Usmaan Mahmood May 08 '20 at 18:17
  • If you want to get the profile image, you would get the profileUrl from the current user object. See [Get A Users Profile](https://firebase.google.com/docs/auth/ios/manage-users#get_a_users_profile). Once you know the URL or have the image, you can then use it wherever you like in the app. – Jay May 08 '20 at 19:12
  • How would that look like in code because I don't fully understand it on the website sorry. This has to apply to whoever has logged in. I have added a userProfile in order to get the profile url as shown in the edited question. – Usmaan Mahmood May 08 '20 at 20:34
  • You *can* do that but Firebase provides a photoUrl property for the current user so why not use it? Then any time you want to display, `let photoUrl = Auth.auth().currentUser.photoUrl` and then see the answer to [this question](https://stackoverflow.com/questions/24231680/loading-downloading-image-from-url-on-swift) for downloading and populating an imageView. On the other hand that works to display the users image to themselves but if you want others to see the image the url can be saved in */users/uid_x/profileUrl* as suggested in your question. Not sure what the question actually is though. – Jay May 08 '20 at 20:50
  • The problem is this *But then how do I then attach it to an image in the profile page of another viewController?* as it's unclear what you're asking. Attach **it**? What is **it** and why do you want to attach **it** to an image? – Jay May 08 '20 at 20:51
  • For example I have a registration scene that includes a name email username and password with an image selector where the user can click it and they can choose an image they want to use as a main profile image, that works. Then in another scene which is the profile page there is an image view where I want that image the was chosen in the registration to display in the image view in the profile page. – Usmaan Mahmood May 08 '20 at 20:56
  • If it wasn't obvious by now I am VERY new to this lol! :). – Usmaan Mahmood May 08 '20 at 21:02
  • OK, so I think you kind of answered your own question. If you know how to store the URL in Firebase, any time you want to use it you load the url from Firebase, and then use it to populate the imageView (as shown in the answer I linked). If you want to use it in 10 different places, you could just load it each time you need it. You could also pass the actual image data (or url) in a segue or assign it to a class var... There are literally 100's of ways to do that which makes the question... and the answer... very broad. – Jay May 08 '20 at 21:16
  • How would that look like in code though because I am really struggling. – Usmaan Mahmood May 08 '20 at 22:07
  • As I mentioned *100's of ways to do that which makes the question... and the answer... very broad.* So how would what look like in code? The Firebase guide linked in my first comment shows specifically how to read data. As you asking how to read data from firebase? Cause' that's really all your doing; read the url from a node and use that to get the image data which you then use for your imageView. You need to make an attempt at that. – Jay May 09 '20 at 14:37
  • please see the last edit I made. – Usmaan Mahmood May 10 '20 at 11:35

1 Answers1

1

The last edit to the question asks this

Now how do I use this in my viewController to actually show the image on the imageView???

This indicates you have a viewController that contains an imageView as you're asking how to assign the downloaded image to that imageView.

The image is downloaded here in your code

static func downloadImage(withURL...
        var downloadedImage:UIImage
        if let data = data {
            downloadedImage = UIImage(data: data)

so a single line of code following that will take the downloadedImage and display it in the imageView

self.myImageView.image = downloadedImage
Jay
  • 34,438
  • 18
  • 52
  • 81
  • Unfortunately that did not work. I copied that line into my viewDidLoad as well and it didn't work either :/. – Usmaan Mahmood May 10 '20 at 16:36
  • @UsmaanMahmood It's working for me as it came directly from a fully functional project. I would suggest deleting this question, creating a new question with the current code you're attempting (based on what I suggested), a clearer description of the issue you're having *with that code* and what troubleshooting you've done. Stating that it did not work doesn't really tell us anything - what didn't work? Did it crash? Was the data var not populated? Did the project not start at all? We need accurate and specific data to assist you - otherwise your questions will be closed. – Jay May 10 '20 at 16:54