Reputation: 458
well, I should load images in the table view, I downloaded and loaded successful, but when I try to show in the table view, they doesn't appear, but, if I do scroll in the table view, the images will appear but the image won't in the middle of the cell.
I'm using swift 4.2
this lines helped me downloaded and loaded images
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = self.resizedImageWith(image: image, targetSize: CGSize(width: 100.0, height: 50.0))
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
in my table view controller, I download the image with this function
func loadImages()
{
for img in arrFavServices
{
if let url = img?.logo
{
let imgDownload = UIImageView()
imgDownload.downloaded(from: url, contentMode: .redraw)
arrImages.append(imgDownload)
}
else
{
let imgDownload = UIImageView()
imgDownload.image = UIImage(named: "logo")
arrImages.append(imgDownload)
}
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.layoutSubviews()
utilActivityIndicator.shared.hideLoader(view: view)
}
}
the array arrFavServices contains all the images' url, and arrImages has all the images previously downloaded. the function loadImages was called in the viewdidload. and I use this function for show the images
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if (arrFavServices[indexPath.section]?.logo) != nil
{
if arrImages[indexPath.section].image != nil
{
cell.imageView?.image = arrImages[indexPath.section].image
cell.imageView?.contentMode = .center
}
}
// Configure the cell...
if let color = arrFavServices[indexPath.section]?.color
{
cell.backgroundColor = UIColor(hexString: color)
}
return cell
}
what is my mistake? help meee please
Upvotes: 2
Views: 1802
Reputation: 418
I will recommend using a Third-party library to load images in tableview.
add this in podfile.
pod 'SDWebImage'
add this simple code in cellForRowAtIndex
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(indexPath.row > arrId.count-1){
// This will return an empty cell if all data is not downloaded and it will avoid the fatal error: index out of range
return UITableViewCell()
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "AlbumCustomCell", for: indexPath) as! AlbumCustomCell
cell.lblId.text = String ( self.arrId[indexPath.row] )
cell.lblTitle.text = self.arrAlbumTitleString[indexPath.row]
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
if let url = URL(string: self.arrAlbumThumbnailURLString[indexPath.row]) {
cell.albumThumbnaiilImage.sd_setImage(with: url, placeholderImage: UIImage(named: "placeholder"), options: .continueInBackground, context: nil)
}
return cell
}
}
This code is required to smoothly scroll the tableview.
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
I am downloading 5000 images and showing them in the table view.
Upvotes: 0
Reputation: 660
I think you have 2 options
You download image async when cell visible ( I recommend )
Download all images and show cell visible
If you are download all images increase your memory usage of app and if too much usage it, iOS will crash your app.
First path:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let logo = arrFavServices[indexPath.section]?.logo {
// We need download image here
cell.imageView?.downloaded(from: logo, contentMode: .center)
}
// Configure the cell...
if let color = arrFavServices[indexPath.section]?.color {
cell.backgroundColor = UIColor(hexString: color)
}
return cell
}
Second Path:
You can use dispatch group. UITableView is waiting for download all images.
// Cache array
var downloadedImages: [UIImage] = []
// Create an instance
var dispatchGroup = DispatchGroup()
func loadImages() {
// Every tick of loop, we enter the group
for img in arrFavServices {
// Join the group
dispatchGroup.enter()
if let url = img?.logo {
let imgDownload = UIImageView()
imgDownload.downloaded(from: url, contentMode: .redraw, completion: { [weak self] downloadedImage in
guard let self = self else { return }
self.downloadedImages.append(downloadedImage)
// And leave group when task is done
dispatchGroup.leave()
})
} else {
let imgDownload = UIImageView()
imgDownload.image = UIImage(named: "logo")
arrImages.append(imgDownload)
// We can leave here too because we add image to array
dispatchGroup.leave()
}
}
// We have to listen group, and that we update tableView or UI todo
dispatchGroup.notify(queue: .main) {
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.layoutSubviews()
self.utilActivityIndicator.shared.hideLoader(view: self.view)
}
}
You can set completion handler like below
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit, completion: ((UIImage) -> Void)?) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
completion?(image)
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit, completion: ((UIImage) -> Void)?) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode, completion: completion)
}
}
Upvotes: 3
Reputation: 329
Mate, why are you not using third party library? Sd_webimage, Kingfisher you can just pod one of this library and in one line of code your image is visible at your desired index of tableview.
Upvotes: -1