如何让UITableView的estimatedHeightForRowAt代理仅在iOS11+运行?
解决iOS11+才执行tableView estimatedHeightForRowAt方法的问题
我来帮你搞定这个需求~你之前的两个方案遇到的问题其实是对Swift协议方法的可用性处理理解有点偏差,下面给你说正确的实现方式:
为什么之前的方案行不通?
- 方案1报错的原因:
tableView(_:estimatedHeightForRowAt:)是从iOS7就存在的UITableViewDelegate可选方法,当你的项目部署目标包含iOS10时,直接给这个方法加@available(iOS 11.0, *)标记,编译器会认为你违反了协议一致性——协议要求这个方法在所有支持的系统版本都能被调用,你不能直接限制它只能在iOS11+生效。 - 方案2的问题:在方法内部加版本判断后,iOS10系统依然会调用这个方法,你返回的任何值都会干扰原有iOS10的estimatedRowHeight逻辑,达不到“不执行该方法”的效果。
正确实现方式:用版本专属扩展分离方法实现
我们可以通过Swift的扩展特性,只在iOS11及以上版本中添加这个方法的实现,iOS10及以下系统根本看不到这个方法,自然就不会执行它。具体代码如下:
1. 主ViewController类(处理iOS10及以下逻辑)
class YourChatViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // 你的属性定义:arrMentionChat、cellHeight、tableView等 var arrMentionChat: [ChatMessageStarModel] = [] var cellHeight: [String: CGFloat] = [:] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self tableView.delegate = self // 配置iOS10及以下的行高逻辑 if #available(iOS 11.0, *) { // iOS11+会走扩展里的estimatedHeight方法,这里无需额外设置 } else { // 按照你iOS10原有的逻辑设置estimatedRowHeight和rowHeight tableView.estimatedRowHeight = 60 // 替换成你原来的默认估算高度 tableView.rowHeight = UITableViewAutomaticDimension } } // 实现其他UITableViewDelegate/DataSource方法... }
2. iOS11+专属扩展(实现自定义estimatedHeight方法)
// 只在iOS11及以上版本生效的扩展 @available(iOS 11.0, *) extension YourChatViewController { func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { let chatMessageStarModel = arrMentionChat[indexPath.row] if let key = chatMessageStarModel.chatMessageMarkerID?.stringValue(), let valueHeight = cellHeight[key], valueHeight > 0.0 { return valueHeight } return UITableViewAutomaticDimension } }
原理说明
- iOS10及以下系统:这个扩展不会被加载,
tableView(_:estimatedHeightForRowAt:)方法不存在,tableView会使用你在viewDidLoad里设置的estimatedRowHeight值,完全遵循原有逻辑。 - iOS11及以上系统:扩展被加载,tableView会调用这个自定义的估算高度方法,执行你想要的逻辑。
这样就完美实现了“iOS11+执行该方法,iOS10及以下不执行”的需求~
内容的提问来源于stack exchange,提问作者Amey
相关产品推荐
相关产品推荐

