I am using SDWebImage library to download image and load into image view inside a table cell.
I want to resize the table cell after the image is downloaded. Please advice. Many thanks.
Cell is not resize correctly after image set into image view
Cell resize correctly after dequeue and load again
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(GagListTableViewCell.cellId, forIndexPath: indexPath) as! GagListTableViewCell
cell.layoutMargins = UIEdgeInsetsZero
let gagDataCommand = gagDataSource[indexPath.row]
if let caption = gagDataCommand.caption {
cell.captionLabel.text = caption
}
if let imageUrlStr = gagDataCommand.images?.normal {
if let imageUrl = NSURL(string: imageUrlStr) {
cell.gagImage.sd_setImageWithURL(imageUrl, placeholderImage: UIImage(named: AppConstants.imagePlaceHolderName), completed: { (image, error, cacheType, url) in
//guess I need to redraw the layout here
})
} else {
//fail to get image url, set placeholder image to the cell instead
cell.gagImage.image = UIImage(named: AppConstants.imagePlaceHolderName)
}
}
return cell
}
You could use automatic dimension for tableview cell.
tableView.rowHeight = UITableViewAutomaticDimension
Related
I've an avatar image in cells in a table. When I touch a cell (highlight) it shows default avatar image instead of the actual image. I'm not sure what is causing this and how to fix. Any help?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as? TableViewCell else {
fatalError("Can't find cell")
}
//...
cell.selectionStyle = .default
self.configCell(cell: cell, indexPath: indexPath)
//...
}
func configCell(cell: TableViewCell, indexPath: IndexPath) {
//...
// Avatar
if let url = URL(string: urlString) {
cell.avatarImageView.image = .defaultImage
cell.tag = indexPath.row
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
DispatchQueue.main.async {
if cell.tag == indexPath.row {
cell.avatarImageView.image = UIImage(data: data)
}
}
}
task.resume()
}
//...
}
If you have an issue only with proper image displaying, I'd suggest working with highlightedImage property of UIImageView.
UITableViewCell has .highlighted property (when the cell is pressed down). Thus, if the cell contains UIImageView inside, then when you select/highlight the cell, the UIImageView will use the .highlightedImage instead of just .image.
So just as a backup and fix to the problem, you could additionally provide/tell UIImageView to display an avatar even when it is highlighted.
update
now images displays as they are loaded, but there still a problem I can't solve.
The images overlaps the content of the cell even the three views are in a vertical stack (first is the image, the next two are label views).
I wonder how can a view overlap other views in a stackview
now my talbe view delegate method looks like this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: BaseTableViewCell!
if let contents = contents {
let content = contents[indexPath.row]
if let imageUrl = content.imageUrl, let url = URL(string: imageUrl) {
cell = tableView.dequeueReusableCell(withIdentifier: "ImageContentRow", for: indexPath) as! ContentWithImageTableViewCell
Alamofire.request(url).responseImage(completionHandler: { (response) in
if let image = response.result.value {
cell.imageView?.image = image
cell.setNeedsLayout()
}
})
}else{
cell = tableView.dequeueReusableCell(withIdentifier: "ContentRow", for: indexPath) as! ContentTableViewCell
}
cell.contentTitleVeiw.text = content.title
cell.contentLeadView.text = content.lead
}
return cell!
}
I'm very new to iOS. I've already tutorials and watched video courses and now I would like to implement my very first app.
I try to read a feed and display the content's title, lead and image (if it has any).
I defined a cell, with an UIMageVeiw, and two UILables, at last I embedded them into a vertical StackView (I set distribution to Fill).
Everything works well, but images don't display automatically, just if I click on the cell, or sroll the TableVeiw.
And even if I set the image view to Aspect Fit (and embedded it into the top tof the vertical stack view), when the image displays it keeps it's original size and overlaps the cell content.
I've trying to find out what I do wrong for two days, but I can't solve it.
I try display data like this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: BaseTableViewCell!
if let contents = contents {
let content = contents[indexPath.row]
if let imageUrl = content.imageUrl, let url = URL(string: imageUrl) {
cell = tableView.dequeueReusableCell(withIdentifier: "ImageContentRow", for: indexPath) as! ContentWithImageTableViewCell
cell.imageView?.af_setImage(withURL: url)
}else{
cell = tableView.dequeueReusableCell(withIdentifier: "ContentRow", for: indexPath) as! ContentTableViewCell
}
cell.contentTitleVeiw.text = content.title
cell.contentLeadView.text = content.lead
}
return cell!
}
The image view cell's view hierarchy looks like this:
My list looks like this after I start my app and data displayed:
After I click on a cell that should display an image or scroll it out and back the result is this:
At least this is my list view controller with the two prototype cells
(one for contents with image, one for without image)
You need to notify the tableView that the image was loaded and that it has to redraw the cell.
Try changing
cell.imageView?.af_setImage(withURL: url)
to
cell.imageView?.af_setImage(withURL: url, completion: { (_) in
self.tableView.beginUpdates()
self.tableView.setNeedsDisplay()
self.tableView.endUpdates()
})
Take a look at my answer here - in the end you might need to explicitly set height on the imageView.
I am downloading and showing thumbnails from server with AlamofireImage , the downloading works fine but when I scroll tableivew cell image changes all the time , I have searched and did not find any solution for example prepareForReuse in custom cell calls. Here is my code :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TrendingCell
let trendingIndex = trendingArray[indexPath.row] as! [String:Any]
if let media = trendingIndex["thumbnails"] as? [String:Any] {
if let thumbnail = media["medium"] as? [String:Any] {
thumbnailURL = String(describing:thumbnail["url"]!)
}
}
Alamofire.request(thumbnailURL).responseImage { response in
if let image = response.result.value {
cell.thumbnail.image = image
}
}
return cell
}
How to avoid image changing when user scrolls tableview ?
As Salman Ghumsani mentioned here :
we can use AlamofireImage extension to set a default thumbnail like this :
//Download and set thumbnail
if let imageURL = URL(string: thumbnailURL), let placeholder = UIImage(named: "Default") {
cell.thumbnail.af_setImage(withURL: imageURL, placeholderImage: placeholder) //set image automatically when download compelete.
}
Now when you scroll table view images did not change.
I have a tableView that contains a UIImageView and if the Image has a URL then the image displays and if not then no Image is displayed. The issue I have is that if there is no Image then a big blank spot occurs in the TableView as if there was an image. Is there a way to reduce the blank spot or hide it (Images below) ? The image is the big UIImageView in the center . This is my code when it comes to the Images
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyFeed", for: indexPath) as! MyFeed
if stream_image_string[indexPath.row].characters.count > 2 {
let strCellImageURL = self.stream_image_string[indexPath.row]
let imgURL: NSURL = NSURL(string: strCellImageURL)!
let request:NSURLRequest = NSURLRequest(url: imgURL as URL)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
DispatchQueue.main.async(execute: { () -> Void in
cell.post_image.image = UIImage(data: data!)
})
});
task.resume()
} else {
cell.post_image!.isHidden = true
cell.post_image!.image = nil
}
return cell
}
Essentially if the String coming back has 2 or more characters then it's a valid URL and the image is downloaded; the part that I am focused on is the else statement and this code
else {
cell.post_image!.isHidden = true
cell.post_image!.image = nil
}
So obviously if it goes in the else statement then there is no image and I set the Image to null or nil then I try to hide the extra white space by setting the Image to hidden however that does not work . Any idea on how I can hide the white space ? I have also been reading this question but it does not work iOS swift imageView cannot be hidden in TableViewCell
Give outlet of image's width and if there is no image then set constant of that outlet to "0".
e.g.
if(!image)
{
widthOfImage.constant = 0
}
I experienced the same problem myself. You need to create 2 cells for this. Like this:
override func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (stream_image_string[indexPath.row] == "")
{
let cell = tableView.dequeueReusableCell (withIdentifier: "noImageMyFeed", for: indexPath) as! noImageMyFeed
return cell
}
else
{
let cell = tableView.dequeueReusableCell (withIdentifier: "MyFeed", for: indexPath) as! MyFeed
return cell
}
}
this video will help you in detail : https://www.youtube.com/watch?v=FAxtWtqeMIM
adapt the video to its own content, create a cell from scratch by simply deleting the image part
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("NewsCell", forIndexPath: indexPath) as! UITableViewCell
cell.imageView?.image = nil
let imgURL = NSURL(string: urlString)
cell.imageView?.image = UIImage(named: "first")
// cell.imageView?.image?.drawInRect(CGRectMake(0,0,50,50))
// or
// cell.imageView?.frame = CGRectMake(0,0,50,50)
// also tried this
cell.imageView?.image = UIImage(named: "first")
cell.imageView?.contentMode = .ScaleAspectFill
cell.imageView?.clipsToBounds = true
Neither seems to make a difference.
When the image loads from the URL online it takes its original size.
I have omitted the code used for asynchronous image downloading because I figure its the same problem here. If not let me know. Thanks !
You should set Mode property of your UIImageView into Aspect Fit where you are showing the image at your cell.
You need to set the contentmode of the imageView either in code or in Interface Builder, and then once you do that you need to usecell.imageView?.clipsToBounds = true