在自定义单元格中获取标签的高度,以便在我的主视图控制器中使用heightForRowAt

我有一个视图控制器,使用一个名为searchCell自定义单元格带内容,我想知道如何获得标签lblLeft的高度,并在tableView(_ tableView:UITableView,heightForRowAt indexPath:IndexPath)中使用它 – > CGFloat函数返回标签的高度。 我在我的主视图控制器中使用的代码:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if searchMode == searching { let cell: MHSearchCell = tableView.dequeueReusableCell(withIdentifier: MHSearchCell.ReusableIdentifier()) as! MHSearchCell cell.helper = helpers[indexPath.row] cell.delegate = self return cell } } 

在我的MHSearchCell中创build标签的代码的一部分,标签在这里连接成一个IBOutlet:

 lblLeft.text = "" if let expertiseCount = helper.expertise { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 5 paragraphStyle.lineBreakMode = .byWordWrapping paragraphStyle.alignment = NSTextAlignment.center lblLeft.numberOfLines = 0 let finalString = expertiseCount.map({$0.name!}).joined(separator: " \u{00B7} ") let finalAttributedString = NSMutableAttributedString(string: finalString, attributes: [NSParagraphStyleAttributeName:paragraphStyle]) lblLeft.attributedText = finalAttributedString } 

我使用自定义扩展来计算NSAttributedString的高度。 “containerWidth”将是您的标签的最大宽度,这很可能是您的单元格的contentView.bounds.size.width。

 extension NSAttributedString { func height(containerWidth: CGFloat) -> CGFloat { let rect = self.boundingRect(with: CGSize.init(width: containerWidth, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil) return ceil(rect.size.height) } func width(containerHeight: CGFloat) -> CGFloat { let rect = self.boundingRect(with: CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: containerHeight), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil) return ceil(rect.size.width) } 

}

一个“技巧”是在cellForRowAtIndexPath之前调用heightForRowAtIndexPath。 您需要创build一个占位符单元格并保存对其的引用。 然后你做这样的事情:

 // Init this once and early var searchCellPlaceholder = SearchCell() // Use whatever the default initializer is func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let object = data[indexPath.row] // Keep reusing this cell and populate it with the new object text, use the configure method in cellForRowAtIndex too. configureCell(cell: searchCellPlaceholder object: object) // Get the height of the label after the text was applied let height = searchCell.label.height(containerWidth: serachCell.contentView.bounds.size.width) return height } 

您不希望在heightForRowAtIndexPath中初始化占位符单元格,因为每次调用该对象时,都会真正杀死您的性能以初始化对象。 这就是为什么你从头开始初始化它,并继续重用它。

//

如果你使用自动布局,你也可以看看如何让UITableView自动为你设置单元格的高度。 这可能是一个更好的select。

第一种方法要么使用自动尺寸

1)在标签上应用适当的限制检查下面的图像。

在这里输入图像说明

确保故事板中的标签行被设置为0

现在在控制器类中这样做:

 //MArk-: ViewDidLoad override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. yourTableView.estimatedRowHeight = 142.0 // Default cell height from storyboard yourTableView.rowHeight = UITableViewAutomaticDimension } 

表格function – :

  public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{ return UITableViewAutomaticDimension } 

另一种计算估计HeightForLabel的方法 –

1)如上所述对标签应用相同的约束

2)使用NSString的boundingRect方法从标签中查找单元格的确切高度 – :

表视图function – :

 extension ViewController : UITableViewDelegate,UITableViewDataSource{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return value.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? testingCell cell?.textlabel.text = value[indexPath.row] return cell! } // Number of sections in table func numberOfSections(in tableView: UITableView) -> Int { return 1 }// Default is 1 if not implemented public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{ let text = value[indexPath.row] let estimatedheight = calculateEstimatedHeight(text: text) return estimatedheight.height } func calculateEstimatedHeight(text:String) -> CGRect{ let size = CGSize(width: view.frame.width, height: 1000) let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin) let attribute = [NSFontAttributeName:UIFont.systemFont(ofSize: 17)] let estimatedHeight = NSString(string: text).boundingRect(with: size, options: options, attributes: attribute, context: nil) return estimatedHeight } 

记得-:

1)为标签提供相同的字体大小。

2)多行标签使用选项为.usesLineFragmentOrigin

CustomCellClass-:

 import UIKit class testingCell: UITableViewCell { @IBOutlet weak var textlabel: UILabel! 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 } }