Xcode9.2 Swift:插入不可见TableViewCell后TextField无法成为FirstResponder解决方法
解决TableView插入Cell后不可见时设置第一响应者崩溃的问题
问题根源
你遇到的致命错误核心原因很明确:ttableView.cellForRow(at:)这个方法仅会返回当前屏幕可见范围内的Cell。当插入的Cell不在当前显示区域时,该方法会返回nil,而你用as!强制解包可选值,直接触发了"Unexpectedly found nil"的崩溃。
解决方案
这里提供两种可靠的解决思路,你可以根据需求选择:
方案1:利用TableView代理方法设置第一响应者(推荐)
把设置第一响应者的逻辑放到tableView(_:willDisplay:forRowAt:)代理方法中——这个方法会在Cell即将显示到屏幕上时被调用,不管Cell是本来就在可见区域,还是插入后滚动过来的,都能稳定触发:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { // 只针对刚插入的第0行Cell做处理 guard indexPath.row == 0, let customCell = cell as? TableViewCell else { return } customCell.textField.placeholder = "input anything ..." customCell.textField.becomeFirstResponder() }
然后修改你的按钮点击事件代码,去掉原来获取Cell并设置的部分,只保留数据更新和滚动逻辑:
@objc func RightNavigationButtonAdd(_ sender: UIBarButtonItem) { array.insert("", at: 0) ttableView.insertRows(at: [IndexPath(row:0, section:0)], with: .top) ttableView.scrollToRow(at: IndexPath(row:0, section:0), at: .top, animated: true) }
这种方式完全贴合TableView的生命周期逻辑,从根源上避免了Cell不可见的问题。
方案2:等待滚动完成后再设置第一响应者
如果你不想修改代理方法,可以监听滚动动画的完成事件,在滚动结束后再安全获取Cell并设置第一响应者。利用CATransaction来监听动画完成:
@objc func RightNavigationButtonAdd(_ sender: UIBarButtonItem) { array.insert("", at: 0) ttableView.insertRows(at: [IndexPath(row:0, section:0)], with: .top) // 监听滚动动画完成 CATransaction.begin() CATransaction.setCompletionBlock { let targetIndex = IndexPath(row: 0, section: 0) // 用可选绑定安全处理,避免强制解包崩溃 if let cell = self.ttableView.cellForRow(at: targetIndex) as? TableViewCell { cell.textField.placeholder = "input anything ..." cell.textField.becomeFirstResponder() } } ttableView.scrollToRow(at: IndexPath(row:0, section:0), at: .top, animated: true) CATransaction.commit() }
这里额外增加了可选绑定判断,即使极端情况下Cell仍不可见,也不会触发崩溃,只是不激活输入框而已。
额外提示
永远避免用as!这种强制解包的方式处理TableView的Cell——你无法保证Cell一定存在。尽量用if let或guard let的可选绑定来安全处理,能有效避免这类崩溃。
内容的提问来源于stack exchange,提问作者TakeYourMark
相关产品推荐
相关产品推荐

