I am showing an image in a UITableView, the image will have different sizes and it is downloaded via JSON, with the following code the image is shown correctly scaled but there are some large spaces up and down (green color). How could I eliminate those spaces?
The image has the constraints top, bottom, left and right to 0 to be able to use the autolayout
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
struct JsonSosTalleres : Codable {
let titulo : String
let image : String
}
private var datosOfertas = [JsonSosTalleres]()
class ImageLoader {
var cache = NSCache<AnyObject, AnyObject>()
class var sharedInstance : ImageLoader {
struct Static {
static let instance : ImageLoader = ImageLoader()
}
return Static.instance
}
func imageForUrl(urlString: String, completionHandler:@escaping (_ image: UIImage?, _ url: String) -> ()) {
let data: NSData? = self.cache.object(forKey: urlString as AnyObject) as? NSData
if let imageData = data {
let image = UIImage(data: imageData as Data)
DispatchQueue.main.async {
completionHandler(image, urlString)
}
return
}
let downloadTask: URLSessionDataTask = URLSession.shared.dataTask(with: URL.init(string: urlString)!) { (data, response, error) in
if error == nil {
if data != nil {
let image = UIImage.init(data: data!)
self.cache.setObject(data! as AnyObject, forKey: urlString as AnyObject)
DispatchQueue.main.async {
completionHandler(image, urlString)
}
}
} else {
completionHandler(nil, urlString)
}
}
downloadTask.resume()
}
}
@IBOutlet weak var tabla: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
downloadJson()
tabla.estimatedRowHeight = 40.0
tabla.rowHeight = UITableViewAutomaticDimension
tabla.tableFooterView = UIView()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datosOfertas.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tabla.dequeueReusableCell(withIdentifier: "ofertacell") as? TableViewCell else { return UITableViewCell() }
let fimage = datosOfertas[indexPath.row].image
ImageLoader.sharedInstance.imageForUrl(urlString: fimage, completionHandler: { (image, url) in
if image != nil {
tableView.beginUpdates()
cell.imagen.image = image
tableView.endUpdates()
}
})
return cell
}
// download json
let url = URL(string: "http://sostalleres.com/test.json")
func downloadJson() {
guard let downloadURL = url else { return }
URLSession.shared.dataTask(with: downloadURL) { data, urlResponse, error in
guard let data = data, error == nil, urlResponse != nil else {
print("something is wrong")
return
}
print("downloaded")
do
{
let decoder = JSONDecoder()
self.datosOfertas = [try decoder.decode(JsonSosTalleres.self, from: data)]
DispatchQueue.main.async {
self.tabla.reloadData()
}
} catch {
print("something wrong after downloaded")
}
}.resume()
}
}
and in TableViewCell.swift :
class TableViewCell: UITableViewCell {
@IBOutlet weak var imagen: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I would appreciate if you can guide me in any solution.
You have to calculate the new height and width and with them apply the scale and use tableView.beginUpdates()
and tableView.endUpdates()
, with the following code you should work without problem.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tabla.dequeueReusableCell(withIdentifier: "ofertacell") as? TableViewCell else { return UITableViewCell() }
let fimage = datosOfertas[indexPath.row].image
ImageLoader.sharedInstance.imageForUrl(urlString: encoded!, completionHandler: { (image, url) in
if image != nil {
let newWidth = self.self.imagenDetalle.frame.width
let scale = newWidth/(image?.size.width)!
let newHeight = (image?.size.height)! * scale
tableView.beginUpdates()
UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
image?.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
cell.imagen.image = newImage
tableView.endUpdates()
}
})
return cell
}
happy coding!