Faheem
Faheem

Reputation: 117

Download URL of firebase storage not working

I'm using the firebase for chat application and I've already stored the images in firebase storage now I want to get the url to fetch the user profile but it's not working even I've tried but nothing is working

Here is the function on line 3rd it generates an error (Value of type 'DatabaseReference' has no member 'downloadURL')

 func downloadURL(for path: String, completion: @escaping (Result<URL, Error>) -> Void) {
        let refrence = database.child(path)
        
        
            refrence.downloadURL(completion: { url, error in //here downnloadUrl not working perfectly
                guard let url = url, error == nil else {
                    completion(.failure(StorageErrors.failedToGetDownloadUrl))
                    return
                }
                completion(.success(url))
            })
    }

NetworkingService Class

struct NetworkingService{
    static let shared = NetworkingService()
    private init(){
        
    }
    private let database = Database.database().reference() //creating refrence

    public func test(){
        database.child("name").setValue(["faheem":true])
    }
 
    
   static func emailForImage(emailAddress: String) -> String{
  
        var safeEmail = emailAddress.replacingOccurrences(of: ".", with: "-")
        safeEmail = safeEmail.replacingOccurrences(of: "@", with: "-")
        return safeEmail
    }
    
    
     func downloadURL(for path: String, completion: @escaping (Result<URL, Error>) -> Void) {
        let refrence = database.child(path)
            refrence.downloadURL(completion: { url, error in
                guard let url = url, error == nil else {
                    completion(.failure(StorageErrors.failedToGetDownloadUrl))
                    return
                }
                completion(.success(url))
            })
    }
   

    func userExists(email: String,completion: @escaping((Bool) -> Void)){ //return boolen
        
        var safeEmail = email.replacingOccurrences(of: ".", with: "-")
        safeEmail = safeEmail.replacingOccurrences(of: "@", with: "-")

        database.child(safeEmail).observeSingleEvent(of: .value) { (snapshot) in
            
            
            guard let foundEmail = snapshot.value as? String else {
                completion(false)
                return
            }
        }
        completion(true)
    }
    
    
    func insertUser(user: CUser, completion: @escaping(Result<CUser,Error>) -> Void){
        database.child(user.identifier).setValue(user.getDict) { (err, dbRef) in
           
            if err != nil{
                completion(.failure(err!))
            }else{
                completion(.success(user))
            }
        }
    }

   
        
    }

StoreManager Class

struct StoreManager{
    
    static let shared = StoreManager()
    private let storageRefrence = Storage.storage().reference()
    
    func uploadProfilePic(data: Data, fileName: String, completion: @escaping(Result<String,Error>) -> Void){
        storageRefrence.child("images/\(fileName)").putData(data,metadata: nil) { (metaData, error) in
            
            guard error == nil else {
                completion(.failure(AppError.failedToUpload))
                print("faheem ye he error \(error?.localizedDescription)")
                return
            }
            
            self.storageRefrence.child("images/\(fileName)").downloadURL { (url, error) in
                guard let url = url else {
                    completion(.failure(AppError.failedtoDownloadUrl))
                    return
                }
                let urlString = url.absoluteString
                print("download url is\(urlString)")
                completion(.success(urlString))
            }
        }
        
    }
}

SignupUserClass

class SignUpUserViewController: UIViewController {

    
    @IBOutlet weak var userProfile: UIImageView!
    @IBOutlet weak var lname: UITextField!
    @IBOutlet weak var fname: UITextField!
    @IBOutlet weak var email: UITextField!
    @IBOutlet weak var password: UITextField!
    var imagePicker = UIImagePickerController() // for imagepicker
    private let spinner = JGProgressHUD(style: .dark)
    var user:CUser!
    override func viewDidLoad() {
        super.viewDidLoad()

        password.isSecureTextEntry = true
        userProfile.layer.masksToBounds = true
        userProfile.layer.borderWidth = 2
        userProfile.layer.borderColor = UIColor.lightGray.cgColor
        userProfile.layer.cornerRadius = userProfile.frame.size.height / 2
        // for rounder image
        
        userProfile.isUserInteractionEnabled = true /
        let gesture = UITapGestureRecognizer(target: self, action: #selector(userProfileChange)) //photopcker
        userProfile.addGestureRecognizer(gesture)

    }
    
    @objc private func userProfileChange(){
        print("profile pic changed")
        getPhoto()
        
    }
    private func insertUser(_ user:CUser){
        NetworkingService.shared.insertUser(user: user) { (result) in
            switch result{
            case .success(let user):
                print("User inserted: ", user.getDict)
                CUser.shared = user
                print("sahed Data is fahem\(CUser.shared)")
            case .failure(let error):
                print("Error: ",error.localizedDescription)
                self.showAlert(message: error.localizedDescription)
            }
        }
    }
    private func createUser(_ user:CUser){
        FirebaseAuth.Auth.auth().createUser(withEmail: user.email, password: user.password) { [weak self] (respomse, error) in
            guard let data = respomse else {
                print("Error: ",error?.localizedDescription ?? "")
                self?.showAlert(message: error?.localizedDescription ?? "")
                return
            }
            self?.insertUser(user)
        }
    }
    
    private func uploadImage(_ imageData:Data) {
        
        StoreManager.shared.uploadProfilePic(data: imageData, fileName: user.imageName) { (result) in
            switch result{
            case .success(let url):
                self.user.imageURL = url
                self.createUser(self.user)
            case .failure(let error):
                print("Error: ",error.localizedDescription)
                self.showAlert(message: error.localizedDescription)
            }
        }
    }

    // register User
    @IBAction func register(_ sender: UIButton) {
        if checkTextFields([email,password,fname,lname]) {
            showAlert(message: "Some fields are missing")
        }else{
            spinner.show(in: self.view)
            NetworkingService.shared.userExists(email: email.text!) { (response) in//checking user through email
                self.spinner.dismiss()
                guard response != nil else { //measn user exists
                    self.showAlert(message: "user account already exits we verify through email")
                    return
                }
                self.user = CUser(firstName: self.fname.text!, lastName: self.lname.text!, email: self.email.text!, password: self.password.text!, imageURL: "")
                /*image url is nil becuase we not upload the image here wehn calling the upload image method
                 then after setting create user method here we only setting the data in user model and url nil*/
                if let userImage = self.userProfile.image!.jpegData(compressionQuality: 0.2) {
                    self.uploadImage(userImage)
                }else{
                    print("Error: Image cannot be compressed")
                }
            }
            
        }
    }
    
    
    func checkTextFields(_ textfields:[UITextField]) -> Bool{
        for textfield in textfields {
            return textfield.text?.isEmpty == true ? true: false
        }
        return true
    }
    func gotOLogin(){
        guard let loginController = self.storyboard?.instantiateViewController(withIdentifier: String(describing: LoginUserViewController.self)) as? LoginUserViewController else {return}
        self.navigationController?.pushViewController(loginController, animated: true)
    }
    func showAlert(title:String = "Error", message:String){
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let ok = UIAlertAction(title: "ok", style:.default, handler: nil)
        alertController.addAction(ok)
        self.present(alertController, animated: true, completion: nil)
    }
    
}


extension SignUpUserViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate{
    
    func getPhoto(){
        let actionSheet = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet)
        actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        actionSheet.addAction(UIAlertAction(title: "Take Photo", style: .default, handler: {
            [weak self] _ in
            self?.presentCamera()
        }))
        actionSheet.addAction(UIAlertAction(title: "Choose Photo", style: .default, handler: { [weak self] _ in
           
            self?.profilePhotoPicker()
        }))
        present(actionSheet, animated: true, completion: nil)
    }
    
    func presentCamera(){ //not allowed in simualtor to capture photo
        imagePicker.sourceType = .camera
        imagePicker.delegate = self
        imagePicker.allowsEditing = true
        present(imagePicker, animated: true, completion: nil)
    }
    
    func profilePhotoPicker(){
        imagePicker.sourceType = .photoLibrary
        imagePicker.delegate = self
        imagePicker.allowsEditing = true
        present(imagePicker, animated: true, completion: nil)
        
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { //called when select photo
        print(info)
        userProfile.image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
        imagePicker.dismiss(animated: true, completion: nil)
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
        
    }

}

ProfileViewcontroler here is getProfilePic fun i already get all the necessary thing but issue is that in networking class download url is not working

class ProfileViewController: UIViewController {

    var logoutUser = ["lgout"]
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var currentUserPic: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(UINib(nibName: String(describing: ProfileCell.self), bundle: .main), forCellReuseIdentifier: String(describing: ProfileCell.self))
    }
    
    func getProfilePic(){
        guard let userEmail = UserDefaults.standard.value(forKey: "useremail") as? String else {
        return}
        
        let userEmailForPic = NetworkingService.emailForImage(emailAddress: userEmail)
        let fileName = userEmailForPic + "_profile_image_jpg"
        let patheStorage = "images/"+fileName//here i  want to fetch the pic but in netwroking class downnload url not working
        
        
    }
  
    
}

Upvotes: 2

Views: 572

Answers (1)

Dharmaraj
Dharmaraj

Reputation: 50850

Firebase Realtime Database and Firebase Storage are separated services. You should be using downloadURL on a storage reference:

func downloadURL(for path: String, completion: @escaping (Result<URL, Error>) -> Void) {
    let reference = Storage.storage().reference().child(path)
        
    reference.downloadURL(completion: { url, error in 
        guard let url = url, error == nil else {
                    
            completion(.failure(StorageErrors.failedToGetDownloadUrl))
                    return
        }
        completion(.success(url))
    })
}

Upvotes: 2

Related Questions