In my app i want hide keyboard when i start scrolling UITableView. I search about this in internet, and most answer is subclassing UITableView (http://stackoverflow.com/questions/3499810/tapping-a-uiscrollview-to-hide-the-keyboard).
I made subclass but it's dont work.
#import <UIKit/UIKit.h>
@protocol MyUITableViewDelegate <NSObject>
@optional
- (void)myUITableViewTouchesBegan;
@end
@interface MyUITableView : UITableView <UITableViewDelegate, UIScrollViewDelegate> {
id<MyUITableViewDelegate> delegate;
}
@end
.m file
#import "MyUITableView.h"
@implementation MyUITableView
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(@"delegate scrollView"); //this is dont'work
[super scrollViewDidScroll:scrollView];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"delegate myUITableViewTouchesBegan"); // work only here
[delegate myUITableViewTouchesBegan];
[super touchesBegan:touches withEvent:event];
}
- (void)dealloc {
...
I use this class like this. But delegate function myUITableViewTouchesBegan don't work in ViewController
.h
#import <UIKit/UIKit.h>
#import "MyUITableView.h"
@interface FirstViewController : UIViewController <UITableViewDelegate, UISearchBarDelegate, MyUITableViewDelegate> {
MyUITableView *myTableView;
UISearchBar *searchBar;
}
@property(nonatomic,retain) IBOutlet MyUITableView *myTableView;
...
.m
- (void) myUITableViewTouchesBegan{
NSLog(@"myUITableViewTouchesBegan");
[searchBar resignFirstResponder];
}
I have some troubles with this implemenation:
1) myUITableViewTouchesBegan dont work in ViewController
2) NSLog from MyUITableView.m - NSLog(@"delegate myUITableViewTouchesBegan"); work only when i touch table. How made it's work also when i start scrolling?
I try override scrollViewDidScroll but comiler said that MyUITableVIew may be don't respond on this string [super scrollViewDidScroll:scrollView];
Not sure why you need to subclass UITableView for this.
In the view controller that contains the plain UITableView, try adding this:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[searchBar resignFirstResponder];
}
Here is the cleanest way to achieve this in iOS 7.0 and above:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
Or to dismiss when touch:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
Or in Swift:
tableView.keyboardDismissMode = .onDrag
Or to dismiss interactively when scrolling:
tableView.keyboardDismissMode = .interactive
You can do this right in Interface Builder. Select your UITableView
and open the Attributes Inspector. In the Scroll View section set the Keyboard field to Dismiss on Drag.
Just to add an update to the answers above. The below worked for me in Swift 1.2
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.OnDrag
or
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.Interactive
Working solution without writing single line of code in your Controller:
As your question is to handle the hide keyboard with one condition only (on scroll).
But here I am recommending one solution to handle textfield and keyboard together which works like charm for UIViewController, UITableView and UIScrollView. The interesting fact is that You do not need to write any single line of code.
Here you go: TPKeyboardAvoiding - An awesome solution to handle keyboard and scroll
Task
Hide keyboard programmatically when scroll UITableView in Swift 3
Details
xCode 8.2.1, swift 3
Solution
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !tableView.isDecelerating {
view.endEditing(true)
}
}
Full Sample
ViewController
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
}
// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
cell.textLabel?.text = "Title"
cell.detailTextLabel?.text = "\(indexPath)"
return cell
}
}
// MARK: - UITableViewDelegate
extension ViewController: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !tableView.isDecelerating {
view.endEditing(true)
}
}
}
StoryBoard
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_4399357" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<searchBar contentMode="redraw" translatesAutoresizingMaskIntoConstraints="NO" id="wU1-dV-ueB">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<textInputTraits key="textInputTraits"/>
</searchBar>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="interactive" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="L52-4c-UtT">
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="wU1-dV-ueB" firstAttribute="bottom" secondItem="L52-4c-UtT" secondAttribute="top" id="0WF-07-qY1"/>
<constraint firstAttribute="trailing" secondItem="wU1-dV-ueB" secondAttribute="trailing" id="3Mj-h0-IvO"/>
<constraint firstItem="wU1-dV-ueB" firstAttribute="leading" secondItem="L52-4c-UtT" secondAttribute="leading" id="8W5-9j-2Rg"/>
<constraint firstItem="wU1-dV-ueB" firstAttribute="trailing" secondItem="L52-4c-UtT" secondAttribute="trailing" id="crK-dR-UYf"/>
<constraint firstItem="wU1-dV-ueB" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="mPe-bp-Dxw"/>
<constraint firstItem="L52-4c-UtT" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="oIo-DI-vLh"/>
<constraint firstItem="wU1-dV-ueB" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="tVC-UR-PA4"/>
</constraints>
</view>
<connections>
<outlet property="searchBar" destination="wU1-dV-ueB" id="xJf-bq-4t9"/>
<outlet property="tableView" destination="L52-4c-UtT" id="F0T-yb-h5r"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-79.200000000000003" y="137.18140929535232"/>
</scene>
</scenes>
</document>
Result