簡要:對于 UITableView、UICollectionView,如果要判斷用戶是否正在拖拽,要使用
isTracking屬性代替isDragging屬性
在 iOS 里,鍵盤彈起之后,如果用戶想讓鍵盤收起,一個常見的做法是當用戶上下劃動一下 tableView 的時候就把鍵盤收起。比如京東商品評論就是這么做的。

那么如何實現(xiàn)這個效果呢?最簡單的想法是:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self.view endEditing:YES];
}
但這樣寫有一個問題:除了用戶手動地上下劃動,其他原因造成的滾動也會觸發(fā)這個回調(diào)函數(shù)。例如,當鍵盤彈出的時候,為了讓 tableView 的內(nèi)容能完全顯示,往往會將 tableView 的底部 inset 改為鍵盤高度,此時也會觸發(fā)scrollViewDidScroll:事件。如果像上面寫的話,就會導致鍵盤又被收起來了。
所以,我們自然想到用 scrollView 的isDragging屬性來判斷一下滾動的原因,是否是用戶拖拽導致的:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.isDragging) {
[self.view endEditing:YES];
}
}
理論上這樣寫應(yīng)該沒有任何問題,然而實際卻不能用!因為測試發(fā)現(xiàn),即使不是用戶劃動,isDragging屬性也可能為YES。比如上面的例子,由于改變 inset 導致的滾動,用戶并沒有拖拽,然而isDragging屬性仍為YES。
也就是說,isDragging屬性在 UITableView 上是不能用的,它的值并不總是正確,并不能正確反映出用戶是否在拖拽。UICollectionView 也有同樣的問題。
要解決這個問題,我們只能用isTracking代替isDragging。所以改成:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.isTracking) {
[self.view endEditing:YES];
}
}
就沒有問題了。
查了一下蘋果文檔,并沒有相關(guān)的解釋,看來又是官方實現(xiàn)的一個小 bug 了。
p.s. 文中的效果也可以用下面這個方法實現(xiàn):
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.view endEditing:YES];
}