I just set my UITableCell linebreak to byWordWrapping and add this method:
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Now My UITableCell Images are massive, what is the best way to resize them or have the images aspect to fit?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "commentsCell", for: indexPath)
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.detailTextLabel?.numberOfLines = 0
cell.detailTextLabel?.lineBreakMode = .byWordWrapping
if((self.array[indexPath.row]["profileImg"] as! String) == "")
{
cell.textLabel?.text = (self.array[indexPath.row]["username"] as! String)
cell.detailTextLabel?.text = (self.array[indexPath.row]["comment"] as! String)
cell.imageView?.image = UIImage(named: "default.png")
}
else
{
let imgUrl = URL(string:"http://auxpod.com/uploads/" + (self.array[indexPath.row]["profileImg"] as! String))
Alamofire.request(imgUrl!).responseImage { response in
DispatchQueue.main.async {
if let image = response.result.value {
cell.textLabel?.text = (self.array[indexPath.row]["username"] as! String)
cell.detailTextLabel?.text = (self.array[indexPath.row]["comment"] as! String)
cell.imageView?.image = image
}
}
}
}
return cell
}
1-
Don't load the image inside cellForRowAt as it keeps download the image every scroll so use SDWebImage that caches it after first download
2-
Create a custom cell class , hook the the height constraint of the imageView and change it according to the required aspect ratio
imageViewH.constant = imageRealHeight * imageCellWidth / imageRealWidth
Related
I am creating a TableView that starts with an image at the top, approximately 5 cells of parsed json, another image, approximately 3 more cells of parsed json, and another image.
I have 3 custom nibs that I am using. Each one is unique.
I get an "Index out of range" error on the line "let item = page?.collapsibles[indexForSecondSetTableViewCells]"
Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentIndex = indexPath.row - 1
let numberofCarousels = self.page?.carousels.count
let indexAfterCarousels = numberofCarousels ?? 00 + 1
let indexForSecondSetTableViewCells = indexAfterCarousels + 1
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew1")
return cell
}
if indexPath.row == indexAfterCarousels {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew2")
return cell
}
if indexPath.row == indexForSecondSetTableViewCells {
let cell = tableView.dequeueReusableCell(withIdentifier: "collapsibleCell", for: indexPath) as! CollapsiblesTableViewCell
let item = page?.collabsible[indexForSecondSetTableViewCells]
cell.collabsibleTitle.text = item?.title
cell.collabsibleDescription.text = item?.content
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "newsTableViewCell", for: indexPath) as! NewsTableViewCell
let item = page?.carousels[currentIndex]
cell.newsTitle.text = item?.title
cell.newsText.text = item?.caption
cell.newsImage.kf.setImage(with: page?.carousels[currentIndex].imageURL)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (page?.carousels.count ?? 0) + 1 + (page?.collapsibles.count ?? 0)
}
Update: I simplified the code to use the same json object twice and so that each item maps to exactly the cell that it should go to and I still get the "Fatal error: Index out of range" error at row 7 with let item = page?.collapsible[indexPath.row]
New code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew1")
return cell
}
if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsTableViewCell", for: indexPath) as! NewsTableViewCell
let item = page?.carousels[indexPath.row]
cell.newsTitle.text = item?.title
cell.newsText.text = item?.caption
cell.newsImage.kf.setImage(with: page?.carousels[indexPath.row].imageURL)
return cell
}
if indexPath.row == 6 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew2")
return cell
}
if indexPath.row == 7 {
let cell = tableView.dequeueReusableCell(withIdentifier: "collapsibleCell", for: indexPath) as! CollapsiblesTableViewCell
let item = page?.collapsibles[indexPath.row]
cell.collabsibleTitle.text = item?.title
cell.collabsibleDescription.text = item?.content
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 11
}
Try to print("\(indexPath)") in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("\(indexPath)")
}
Then you will know how many rows it successfully shows before crash.
Then in cellForRowAt put conditional break point such it stops when indexPath is the one it crashed.
Now do po (page?.carousels.count ?? 0) + 1 + (page?.collapsibles.count ?? 0)
to see how many rows your tableview has. Most definitely indexForSecondSetTableViewCells is more than the number of rows
Here I attached the gif file. Refer this
In my tableview I have a custom xib cell with autolayout. When I run the project, getting the problem like the gif file.
Its my tableview function
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "requestsCell", for: indexPath) as? RequestsTableViewCell
cell?.backgroundColor = .clear
let passengerName = cell?.viewWithTag(1) as! UILabel
let bookingCreator = cell?.viewWithTag(2) as! UILabel
let department = cell?.viewWithTag(3) as! UILabel
let product = cell?.viewWithTag(4) as! UILabel
passengerName.text = "Muhammed yasheed"
bookingCreator.text = "Muhammed Yasheed"
department.text = "Programming"
product.text = "Flight"
cell?.approvedView.isHidden = false
cell?.cancelView.isHidden = true
return cell!
}
Finally I found the answer. Just add cell?.layoutIfNeeded() in cellForRowAt indexpath
cell?.layoutIfNeeded()
hey i have a tableview with images and some text labels the whole cell is 400 in height and i want to extend it to 700 when i click the cell to make the user see more information of the cell so i wrote this code
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if isExpanded && self.selectedIndex == indexPath{
return 700
}
return 400.0
}
var selectedIndex:IndexPath?
var isExpanded = false
func didExpandCell() {
self.isExpanded = !isExpanded
self.postsTableView.reloadRows(at: [selectedIndex!], with: .automatic)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedIndex = indexPath
self.didExpandCell()
}
but this code requires a .xib file off the Cell, i have tryed to run the app without the code below but it doesnt work and i have tryed it with it and it doesnt work because i need a .xib file for the cell so i was wondering if it is possible that someone could help me with this and just explain how i can this cells epandable without this .xib file of the cell
func unnesseryNibFile(){
//this code goes in the viewDidLoad func and it is required to have a .xib file of the Cell protoype
let nib = UINib.init(nibName: "postTableViewCell", bundle: nil)
self.postsTableView.register(nib, forCellReuseIdentifier: "Cell")
}
here is my 'cellForRowAt'
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PostTableViewCell
// Configure the cell...
let post = self.posts[indexPath.row] as! [String: AnyObject]
cell.locationLabel.text = post["location"] as? String
cell.usernameLabel.text = post["username"] as? String
cell.titleLabel.text = post["title"] as? String
cell.contentTextView.text = post["content"] as? String
if let imageName = post["image"] as? String {
let imageRef = Storage.storage().reference().child("images/\(String(describing: imageName))")
imageRef.getData(maxSize: 25 * 1024 * 1024, completion: { (data, error) -> Void in
if error == nil {
//succeful
let image = UIImage(data: data!)
cell.postImageView.image = image
}else{
//Not Succesful
print("error Downloading The Image\(String(describing: error?.localizedDescription))")
}
})
}
return cell
}
thanks for your time. :)
var savedFaouritePlaces: NSMutableArray = [] //matched strings
Here is the info I get and I want to use this items cell for row at index path
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
guard let cell = tableView.dequeueReusableCell(withIdentifier: "HeartTabCell") as? HeartTabTableViewCell else {
return UITableViewCell()
}
cell.heartTabTitleLabel.text = "Wanna use that title here"
cell.heartTabImageView.image = "wanna use that image here"
return cell
}
You should use indexPath to retrieve each dictionary in that array:
let dict = savedFaouritePlaces[indexPath.row]
cell.heartTabTitleLabel.text = dict["Title"]
cell.heartTabImageView.image = UIImage(named: dict["Image"])
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "HeartTabCell") as? HeartTabTableViewCell
let dictionary = savedFaouritePlaces[indexPath.row]
cell.heartTabTitleLabel.text = dictionary["Title"]
cell.heartTabImageView.image = UIImage(named: dictionary["Image"])
return cell
}
Ok, need a little help here. I'm new to Swift. Here's my issue.
When getting data for my UITableView, I'm calling image data from a url, so there is a slight delay when grabbing reused cells, resulting in the cell showing old data for half a second. I've tried to call func prepareForReuse to reset properties, but it doesn't seem to be working. Any help is appreciated!
Here's my code when calling cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.alpha = 0
let book = books[indexPath.row]
cell.textLabel?.text = book.bookTitle
cell.detailTextLabel?.text = book.postURL
let url = URL(string: book.postPicture)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
cell.alpha = 0
cell.backgroundView = UIImageView(image: UIImage(data: data!))
UIView.animate(withDuration: 0.5, animations: {
cell.alpha = 1
})
}
}
cell.contentView.backgroundColor = UIColor.clear
cell.textLabel?.backgroundColor = cell.contentView.backgroundColor;
cell.detailTextLabel?.backgroundColor = cell.contentView.backgroundColor;
func prepareForReuse(){
cell.alpha = 0
cell.backgroundView = UIImageView(image: UIImage(named: "book.jpg"))
}
return cell
}
You should subclass UITableView cell and inside your custom class override:
import UIKit
class CustomTableViewCell: UITableViewCell {
override func prepareForReuse() {
// your cleanup code
}
}
then in UITableViewDataSource method reuse the custom cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CustomTableViewCell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! CustomTableViewCell
return cell
}