问题
Currently in my code, I'm programmatically adding a UITextView within a UITableViewCell and added the ability to auto-resize the cell based on how much content is typed by the user.
It currently looks like so:
override func viewDidLoad()
{
tableView.estimatedRowHeight = 30.0
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// Dequeue the cell to load data
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
if indexPath.section == 0
{
// Code
}
if indexPath.section == 1
{
let textView: UITextView = UITextView()
textView.delegate = self
textView.textColor = UIColor.black
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
cell.addSubview(textView)
let leadingConstraint = NSLayoutConstraint(item: cell.contentView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: textView, attribute: NSLayoutAttribute.leading, multiplier: 1.0, constant: 8.0)
let trailingConstraint = NSLayoutConstraint(item: cell.contentView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: textView, attribute: NSLayoutAttribute.trailing, multiplier: 1.0, constant: -8.0)
cell.contentView.addConstraint(leadingConstraint)
cell.contentView.addConstraint(trailingConstraint)
let topConstraint = NSLayoutConstraint(item: cell.contentView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: textView, attribute: NSLayoutAttribute.top, multiplier: 1.0, constant: 0)
let bottomConstraint = NSLayoutConstraint(item: cell.contentView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: textView, attribute: NSLayoutAttribute.bottom, multiplier: 1.0, constant: 0)
cell.contentView.addConstraint(topConstraint)
cell.contentView.addConstraint(bottomConstraint)
}
else if indexPath.section == 2
{
// Code
}
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int
{
return 3
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell")
let titleLabel = headerCell?.viewWithTag(1) as! UILabel
if section == 0
{
titleLabel.text = "Title"
}
else if section == 1
{
titleLabel.text = "Title"
}
else if section == 2
{
titleLabel.text = "Title"
}
return headerCell?.contentView
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
{
let footerCell = tableView.dequeueReusableCell(withIdentifier: "FooterCell")
return footerCell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
if indexPath.section == 1
{
return UITableViewAutomaticDimension
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
return 35.0
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
{
return 15.0
}
func textViewDidChange(_ textView: UITextView)
{
tableView.beginUpdates()
tableView.endUpdates()
}
I only care about section 1 because that's the only cell that I want to auto-resize the cell's height. All other sections should maintain a static cell height.
The problem I have is that as soon as I press the enter key for the FIRST time in the UITextView to skip to the next line, I see very quickly some "ghost" cells and get a warning stating:
no index path for table cell being reused
The cell's height DOES dynamically re-size itself accordingly and after the initial return key is pressed, any subsequent new lines does not re-produce the "ghost" cells, but I still get the warnings.
What am I seem to be doing wrong?
Thanks
回答1:
TextView is inherited from scrollView and hence the content size of textView can be greater than frame (In which case textView will scroll). In order for tableView to calculate the automatic size for cell it needs components with implicit size like label or button. So in order for tableView to calculate implicit size for textView you should disable scroll.
textView.isScrollEnabled = false
Should allow your cell to expand :)
EDIT:
Looks like this happens when a reusable cell is used as section header (as in your case) Have a look at this : What is the meaning of the "no index path for table cell being reused" message in iOS 6/7?
Suggestion :
Create a normal xib add a view and return it as a section header else follow the answer posted in above link
回答2:
Try this. Add this method too. func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
回答3:
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{
if(indexPath.row == 0){
return heightForFirstRow
}
return heightForStaticCell
}
来源:https://stackoverflow.com/questions/43061719/dynamic-cell-re-sizing-with-uitextview-within-uitableviewcell-causes-warning