haydg8
haydg8

Reputation: 27

Async load image to custom UITableViewCell partially working

My images dont load into the imageview until you scroll the cell off the table and back on, or go to another view and come back to the the view (redraws the cell).

How do I make them load in correctly?

/////////

My viewDidLoad has this in it:

    tableView.delegate = self
    tableView.dataSource = self

    DispatchQueue.global(qos: .background).async {
        self.getBusinesses()

        DispatchQueue.main.async {

            self.tableView.reloadData()


        }
    }

I call the function download the image here in the .getBusinesses function called in viewDidLoad:

func getBusinesses() -> Array<Business> {

    var businessList = Array<Business>()
    //let id  = 1
    let url = URL(string: "**example**")!
    let data = try? Data(contentsOf: url as URL)
    var isnil = false

    if data == nil{
        isnil = true
    }
    print("is nill is \(isnil)")


    if(data == nil){
        print("network error")
        businessList = []
        return businessList
    }
    else{
        values = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
    }

    let json = JSON(values)

    var i = 0;
    for (key, values) in json {

        var businessReceived = json[key]
        let newBusiness = Business(id: "18", forename: "", surname: "", email: "", password: "", business: true, level: 1, messageGroups: [], problems: [])

        newBusiness.name = businessReceived["name"].stringValue
        newBusiness.description = businessReceived["description"].stringValue
        newBusiness.rating = Int(businessReceived["rating"].doubleValue)
        newBusiness.category = businessReceived["category"].intValue
        newBusiness.distance =  Double(arc4random_uniform(198) + 1)
        newBusiness.image_url  = businessReceived["image"].stringValue
        newBusiness.url  = businessReceived["url"].stringValue
        newBusiness.phone  = businessReceived["phone"].stringValue
        newBusiness.postcode  = businessReceived["postcode"].stringValue
        newBusiness.email = businessReceived["email"].stringValue
        newBusiness.id = businessReceived["user_id"].stringValue

        if(newBusiness.image_url  == ""){
            newBusiness.getImage()

        }
        else{
            newBusiness.image = #imageLiteral(resourceName: "NoImage")
        }


        if(businessReceived["report"].intValue !=  1){
            businessList.append(newBusiness)

        }
    }

    businesses = businessList

    print(businesses.count)
    holdBusinesses = businessList
    return businessList

}

Here in the business object i have this method to download the image from the url and store it in the business object's image property:

 func getImage(){

    if(self.image_url != ""){

        print("runs imageeee")
        var storage = FIRStorage.storage()

        // This is equivalent to creating the full reference
        let storagePath = "http://firebasestorage.googleapis.com\(self.image_url)"
        var storageRef = storage.reference(forURL: storagePath)




        // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
        storageRef.data(withMaxSize: 30 * 1024 * 1024) { data, error in
            if let error = error {
                // Uh-oh, an error occurred!
            } else {
                // Data for "images/island.jpg" is returned
                self.image = UIImage(data: data!)!
                print("returned image")
            }
        }


    }
    else{

        self.image = #imageLiteral(resourceName: "NoImage")

    }

}

I then output it in the tableview here:

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

    let cell  = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for : indexPath) as! BusinessesViewCell


            cell.businessImage.image = businesses[(indexPath as NSIndexPath).row].image


            //.............  

     return cell
}

Upvotes: 0

Views: 148

Answers (2)

Halil İbrahim YILMAZ
Halil İbrahim YILMAZ

Reputation: 730

You can use

cell.businessImage.setNeedsLayout()

Upvotes: 0

Sean Lintern
Sean Lintern

Reputation: 3141

            self.image = UIImage(data: data!)!

should become

    DispatchQueue.main.async {
         self.image = UIImage(data: data!)!
    }

Inside

    storageRef.data(withMaxSize: 30 * 1024 * 1024) { data, error in

EDIT: My initial thought was the download logic was inside the cell, now I know its not.

you either need to call reloadData() on the tableView each time you get to

         self.image = UIImage(data: data!)!

or better yet find out which index you just updated, then called

  tableView.reloadRows:[IndexPath]

Upvotes: 1

Related Questions