Home > Enterprise >  Swift TableView data only loading after scrolling to bottom
Swift TableView data only loading after scrolling to bottom

Time:09-26

I have a code where I am fetching images from URLs and displaying them in a tableview, however the images only show up inside tableview when scrolling down to far bottom of the screen, as show in the image below.

TableView before scrolling to bottom, screenshot

TableView after scrolling to bottom, screenshot

Code for the fetching images and tableView

    @IBOutlet weak var tableView: UITableView!
    let imageArray = [UIImage()]
    let urlArray = ["https://media.api-sports.io/football/teams/50.png","https://media.api-sports.io/football/teams/47.png","https://media.api-sports.io/football/teams/49.png","https://media.api-sports.io/football/teams/46.png","https://media.api-sports.io/football/teams/48.png"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(UINib(nibName: "ImageCell", bundle: nil), forCellReuseIdentifier: "imageCell")        // Do any additional setup after loading the view.
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath) as! ImageCell
        cell.clubImage.load(url: URL(string: urlArray[indexPath.row])!)
        return cell
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return urlArray.count
    }
}

extension UIImageView {
    func load(url: URL) {
        DispatchQueue.global().async { [weak self] in
            if let data = try? Data(contentsOf: url) {
                if let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        self?.image = image
                    }
                }
            }
        }
    }
}

How can I show the images as soon as the app loads?

Thanks

CodePudding user response:

The issue is that the table view is calculating the size of the cell before an image has been loaded. The image view in the cell defaults to a height of zero since it has no content yet. I'd suspect something in the table view implementation causes the cells sizes to be recalculated when reaching the bottom which allows them to appear.

One solution could be to add a constraint to the image view so that it has a fixed size before an image is loaded. The simplest is if all cells can have the same size. If they need different sizes, that would need to be set in cellForRowAt either before loading the image, or the image loading would need to be moved so it's done outside of the cell allowing the cell to be reloaded with the correct size later.

CodePudding user response:

Make your load method with completion:

func load(url: URL, completion: @escaping (UIImage?) -> Void) {
        DispatchQueue.global().async { in
            if let data = try? Data(contentsOf: url) {
                if let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        completion(image)
                    }
                }
            }
        }
    }

Then in cellForRawAt call the method and add your loaded imaged to your imageView:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath) as! ImageCell
        cell.clubImage.load(url: URL(string: urlArray[indexPath.row])!) { image in 
            // display your image here...
            
        }
        return cell
    }
  • Related