How do I get LineBreakMode to work in UITableViewCell? iOS - Swift - ios

I have a header and a body inside my tableviewcells. I'm trying to get the body to wrap but I'm having issues.
This is the code I'm using in my view controller
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("mainCell") as? mainCell {
cell.mainHeader.text = (mainHeader[indexPath.row])
cell.mainBody.text = (mainBody[indexPath.row])
cell.mainBody.numberOfLines = 0
cell.mainBody.lineBreakMode = NSLineBreakMode.ByWordWrapping
return cell
} else {
return mainCell()
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mainHeader.count
}
}
I searched and thought that the numberOfLines = 0 and lineBreakMode = NSLineBreakMode would work but it's obviously not.
Sorry if this is simple, thanks in advance.
#Daven
I know this probably won't help, but I don't think I have that or if I do I'm unsure of what it is. Also updated original code with everything that is in my VC but the vars
I have this for my custom cell
import UIKit
class mainCell: UITableViewCell {
#IBOutlet weak var mainHeader: UILabel!
#IBOutlet weak var mainBody: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func configureCell (text:String) {
mainHeader.text = text
mainBody.text = text
}
}

To make your cell expand as its label grows, you'll need to make sure you've done a few things. Set your tableView's estimatedRowHeight to a value, like
tableView.estimatedRowHeight = 200.0;
tableView.rowHeight = UITableViewAutomaticDimension
or via this method:
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 200.00
}
You also have the option of using this method, but it's not necessary if all your cells are going to vary in height:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
You may also find this tutorial helpful (this is what I used :)). It shows what your autolayout constraints should look like. More information about self-sizing cells is also here.

Assuming you want your cell to expand when the text is longer than one line, you want to set the cell height to be automatic using the delegate function:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
and set the estimated row height using
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return currentInfoSelectorOption.rowHeight + 100
}
Then use autolayout in your cell to set the height. You can do this by setting the top and bottom distance constraints of the cell to the label as a constant value and setting the labels number of lines to 0. This should allow the label to expand and push the cell with it

Related

Cannot Set Dynamic TableView Row Height

I'm trying to set dynamic row height in TableView. But unfortunately is not working.
The only thing is working is to set the heightForRowAt indexPath to a constant number.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 470 //or any other number
}
If I delete this function, or try to set it to automatic the cell will not show at all. Something like this:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
I also tried to use:
self.tableView.estimatedRowHeight = UITableView.automaticDimension //Tried even with a number
self.tableView.rowHeight = UITableView.automaticDimension
But seems nothing to work besides using a constant height in heightForRowAt indexPath function. Which is not what I want, I want cell to be expanded based on content inside the cell.
I also tried to set height in heightForRowAt indexPath function to automatic but set a fixed height on constraints in the content of the cell xib file, still same (I did just to see what happens). So seems, something is wrong around this function.
Note:
My TableView and UITableViewCell are divided in a storyboard and a xib files.
If you want to set the dynamic tableview row height, you must use autolayout.
Please set the constraint on the UI components in the cell as shown in the image below.
I used UILabel as sample code. For UILabel, be sure to set Lines to 0.
Here is the sample code
class ViewController: UIViewController {
let stringArr = ["aaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableView.automaticDimension
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stringArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell else {
return UITableViewCell()
}
cell.label.text = stringArr[indexPath.row]
return cell
}
}
You need to register the cell in the tableview.
tableView.register(UINib(nibName: “YourCellNibName”, bundle: nil), forCellReuseIdentifier: “YourCellReuseIdentifier”)

UITableView returns blank cells

I have a table view with height of cells set to automatic.
Once in a few runs, a few cells in the table are displayed empty (white space). Upon debugging, I noticed that the 'cellForRowAtIndexPath' function returns these cells as usual. Also, every time this bug shows up, the console has this message:
"Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead."
Scrolling up and down a couple of times fixes the issue and cells are displayed.
I use this following functions for height:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
I have been stuck with this for a week and any help would be greatly appreciated!
Edit: Code for the cells:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var row = indexPath.row
tableView.allowsSelection = false;
let cellIdentifier = "testTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! testTableViewCell
let post: PostMdl!
if(row < posts.count) {
post = posts[row]
}
else {
return cell
}
cell.label.delegate = self
cell.label.enabledTextCheckingTypes = NSTextCheckingType.Link.rawValue
cell.label.userInteractionEnabled = true
cell.brandName.text = post.brandName
cell.timeStamp.text = post.timeStamp
cell.brandImg.sd_setImageWithURL(post.brandImgUrl, placeholderImage: UIImage(named: "placeHolder"))
if let img = post.postImg {
cell.mainImg.image = img
} else {
cell.mainImg.image = UIImage(named:"lazyLoad")
}
cell.label.text = post.postTag
cell.labelDistanceFromImg.constant = 30
cell.labelDistanceToBtm.constant = 30
cell.postTag = post.postTag
cell.socNtwkImg.image = UIImage(named: post.socNtwk)
return cell
}
I guess you had set wrong constraints to subviews of UITableViewCell.contentView.
This image shows what I reproduce your error:
Please note the right constaints of red view, it just has Top Left Right Height, lacks bottom constraint, when I add it and it looks good:
Yes, there still have problem that Unable to simultaneously satisfy constraints, we can modify the priority of height constraint, default priority is required(1000), we change to Hight(750), it works!
I don't know your cell's detail, but the error's reason is likely, hope my answer helps you.
Append codes
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return tableView.dequeueReusableCellWithIdentifier("cell")!;
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}
What is your mobile phone version of the iOS?
In the previous iOS8 version I also encountered similar problems.
My method is as follows:
tableView.estimatedRowHeight = 88.0
tableView.rowHeight = UITableViewAutomaticDimension
Hope can help you

Self sizing TableView cell with image and label

hello I have a dynamic TableViewController in which there is one cell which has one image, and labels. I have set constraint of all of them. The problem is its not viewing correctly.
This is how its viewing
Code:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 103
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.setNeedsLayout()
tableView.layoutIfNeeded()
self.tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return newarray.count
}
override
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("requestcell", forIndexPath: indexPath) as! NewRequestTableViewCell
let image : UIImage = UIImage(named: "placeholder_product_image")!
cell.imageView!.image = image
cell.requestTitle.text = "IPHONE 6s PLUS"
cell.DestinationCountry.text = "Pakistan"
return cell
}
I don't know what else to do. Please help how can I have row like I designed
The problem here is the height of your cell
add the following methods in your code: (replacing of course <#cell_height#> by the value of your choice, or by UITableViewAutomaticDimension)
override func tableView(_ tableView: UITableView,
heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return <#cell_height#>;
}
In order for tableView self sizing to work, you need to add constraint to both top and bottom of UILabel.
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 103
I think your trying is right, but you need to increase the estimatedRowHeight. i.e, 300 or 600.
And you need to add constraints on Storyboard suitably.
so just add up, left, right, bottom distance constraints.
Never give the width & height constraints there.
Beside you need to call the cell.contentView.layoutIfNeeded just in the cellForRowAtIndexPath method.
I think it will work then.
Sincerely,
Harri.

Why cellForRowAtIndex doesn't run at all?

I've added TableView to my controller and created custom UITableViewCell. Later, I've tried to run this code:
func tableView(educationTableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> educationCell {
let cell:educationCell = educationTableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! educationCell
print("TableView runs")
return cell
}
but I do not get my print in logs TableView runs. I do not understand what happens and why it doesn't run. Who knows, why this problem appears?
I read other answers in SO, but noone helps =/
need the return value of numberOfRowsInSection greater than 0
Just make sure you have implemented proper DataSource and Delegate for controller, number of rows is greater then 0
import UIKit
class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var items: [String] = ["We", "Heart", "Swift"]
#IBOutlet var tableView: UITableView! //hook this to your storyboard tableview
// MARK: - Controller life cycle stack
override func viewDidLoad() {
super.viewDidLoad()
//confirm table's delegate and data source programmatically
tableView.delegate = self;
tableView.dataSource = self;
}
//table view delegate and data source methods
func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int
{
//number of rows must be greater then 0 to get called "CellForRowAtIndex"
return self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! CraditCardCell
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
print("You selected cell");
}
}
One reason could be because you modified the return type to educationCell, instdead of the standard UITableViewCell. Try changing that.

Adjust cell height with UIImageView on it

I have an imageView on a UITableViewCell, and I want to set height of the cell / imageView to a different value compare what I set in prototype cell. I do not want to implement heightForRowAtIndexPath method, because I do not want to precalculate the height of the content. If UITableViewAutomaticDimension is set and at least on iOS 8 heightForRowAtIndexPath does not need to implement.
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 3
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")!
let iv = cell.viewWithTag(1) as! UIImageView
iv.image = UIImage(named: "img1")
let cs = iv.constraints.first! as NSLayoutConstraint
cs.constant = 100
cell.layoutIfNeeded()
cell.setNeedsUpdateConstraints()
return cell
}
Structure of the prototype:
Although the height of the cell in prototype is set to 44.0 px, but in cellForRowAtIndexPath method I want to override this value with 100.0 px.
It'll not work the way you do.
You should implement delegate method of UITableViewDelegate
func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// calculate size of image and return its height here
}

Resources