Dispatchqueue is not working properly, compiles but does not load storage images

by Konrad Bulanowski   Last Updated April 19, 2019 01:26 AM

The application compiles successfully but it does not seem to load the user profile images. I attempted changing the dispatchqueue for hours but cannot seem to see what the problem is. The properey version should essentially take the profile picture the user selected and assign it to their account and when others see their account they should see that users profile image. Thank you for your help and consideration!

Controller file


import UIKit
import Firebase

class NewMessageController: UITableViewController {

    let cellId = "cellId"
    var users = [User]()

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.backBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel))

        tableView.register(UserCell.self, forCellReuseIdentifier: cellId)

        fetchUser()
    }

    func fetchUser() {
        let rootRef = Database.database().reference()
        let query = rootRef.child("users").queryOrdered(byChild: "username")
        query.observe(.value) { (snapshot) in
            for child in snapshot.children.allObjects as! [DataSnapshot] {
                if let value = child.value as? NSDictionary {
                    let user = User()
                    let username = value["username"] as? String ?? "Name not found"
                    let email = value["email"] as? String ?? "Email not found"
                    user.username = username
                    user.email = email
                    self.users.append(user)
                    DispatchQueue.main.async { self.tableView.reloadData() }
                }
            }
        }
    }

    @objc func handleCancel() {
        dismiss(animated: true, completion: nil)
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return users.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! UserCell
        let user = users[indexPath.row]
        cell.textLabel?.text = user.username
        cell.detailTextLabel?.text = user.email


        if let profileImageURL = user.profileImageUrl{

            cell.profileImageView.loadImageUsingCacheWithUrlString(urlString: profileImageURL)

        }

        return cell
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 72
    }
}

class UserCell: UITableViewCell {

    override func layoutSubviews() {
        super.layoutSubviews()

        textLabel?.frame = CGRect(x:64, y:textLabel!.frame.origin.y - 2, width: textLabel!.frame.width, height: textLabel!.frame.height)

       detailTextLabel?.frame = CGRect(x:64, y:detailTextLabel!.frame.origin.y + 2, width: detailTextLabel!.frame.width, height: detailTextLabel!.frame.height)
    }

    let profileImageView: UIImageView = {
        let imageView = UIImageView()
//        imageView.image = UIImage(named: "head")
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.layer.cornerRadius = 24
        imageView.layer.masksToBounds = true
        imageView.contentMode = .scaleAspectFill
        return imageView
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
        addSubview(profileImageView)

        profileImageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true

        profileImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        profileImageView.widthAnchor.constraint(equalToConstant: 48).isActive = true
        profileImageView.heightAnchor.constraint(equalToConstant: 48).isActive = true




    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension file

import UIKit

let imageCache = NSCache<AnyObject, AnyObject>()

extension UIImageView {

    func loadImageUsingCacheWithUrlString(urlString: String){

        self.image = nil

        if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
            self.image = cachedImage
            return
        }

        let url = URL(string: urlString)


        URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
            //this mean download hit an error so lets return out.
            if error != nil {
                print(error!)
                return
            }

            DispatchQueue.main.async(execute: {
                if let downloadImage = UIImage(data: data!){
                    imageCache.setObject(downloadImage, forKey: urlString as AnyObject)
                    self.image = downloadImage
                }

            })
        }).resume()

    }


}


Related Questions


Updated June 23, 2017 06:26 AM

Updated October 15, 2018 02:26 AM

Updated March 03, 2019 06:26 AM

Updated September 16, 2018 08:26 AM