steff feyens steff feyens - 19 days ago 6
Swift Question

Downloading Image extremely slow

I'm trying to create my first little chat app. The users can change their profile picture when registering. I'm trying to display the profile picture each time the users chats with another users. Everything works but the problem is that some pictures are extremely slow. This causes that some messages will display fast and others very slow.

My Code:

override func viewDidLoad() {
super.viewDidLoad()

messagesTableView.delegate = self
messagesTableView.dataSource = self
messagesTableView.clearsContextBeforeDrawing = true

getMessages()
}

func getMessages() {
let ref = FIRDatabase.database().reference()
let messagesReference = ref.child("Messages")

// GETTING THE MESSAGES AND USERNAMES
messagesReference.observe(.childAdded, with: { (snapshot) in

if let dictionary = snapshot.value as? [String: AnyObject] {

let usernameReference = ref.child("Usernames").child(dictionary["Sender"] as! String)

// CONVERTING THE USERNAME INTO THE UID
usernameReference.observeSingleEvent(of: .value, with: { (snapshot2) in

if let dictionary2 = snapshot2.value as? [String: AnyObject] {
let uid = dictionary2["UID"] as! String

let uidReference = ref.child("Users").child(uid)

// GETTING THE PROFILE IMAGE LINK
uidReference.observeSingleEvent(of: .value, with: { (snapshot1) in

if let dictionary1 = snapshot1.value as? [String: AnyObject] {
let imageLink = dictionary1["Image Link"] as! String

// DOWNLOADING THE PROFILE IMAGE FROM THE LINK
let url = URL(string: imageLink)
URLSession.shared.dataTask(with: url!) { (data, response, error) in

if(error != nil){
print(error as Any)
return
}

let profileImage = UIImage(data: data!)

DispatchQueue.main.async {
let message = Messages()
message.setValuesForKeys(dictionary)
message.profileImage = profileImage

self.messages.append(message)

self.messagesTableView.reloadData()
}
}.resume()
}
}, withCancel: nil)
}
}, withCancel: nil)
}
}, withCancel: nil)
}

func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return messages.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellId")

DispatchQueue.main.async {
let message = self.messages[indexPath.row]
cell.textLabel?.text = message.Sender
cell.detailTextLabel?.text = message.Message
cell.imageView?.image = message.profileImage
}

return cell
}


This image is downloading and displaying fast:
-> https://firebasestorage.googleapis.com/v0/b/chat-62eba.appspot.com/o/ProfileImages%2F766FB2E4-9153-4F99-81B2-14B2E3677459.png?alt=media&token=306e32e5-21b6-4ff5-918b-79c6173f0ae9

And this one is downloading and displaying extremely slow:
-> https://firebasestorage.googleapis.com/v0/b/chat-62eba.appspot.com/o/ProfileImages%2F0B758D09-58FE-4771-BA29-16FB0EAB2FFD.png?alt=media&token=8d886b45-dd14-4157-b647-217122b6d331

I've searched for hours to find a solution but haven't found one yet. I hope someone can help me! Thanks

Answer

Looking at your code you are using Firebase, so I guess you have no additional backend. The issue is really at the upload-side. You need to optimise the size and thus, crop the image.

func resize(image: UIImage, size: CGSize) -> UIImage? {

    let scale = size.width / image.size.width
    let height = image.size.height * scale
    UIGraphicsBeginImageContext(CGSize(width: size.width, height: height))
    image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: height))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

    return newImage
}