I have a normal set up for a textfield with numberpad and the dismiss keyboard and resignFirstResponder actions in place, but when I tap on the background the numeric keyboard changes to the normal keyboard and then when I tap the background again the keyboard dismisses - STRANGE! How can I dismiss the numeric keyboard with one tap to the background?
self.textField.delegate = self
textField.keyboardType = UIKeyboardType.DecimalPad
#IBAction func tapBackground(sender: AnyObject) {
view.endEditing(true)
}
#IBAction func viewTapped(sender: AnyObject) {
textField.resignFirstResponder()
}
Try following this may help you :)
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: "handleTapGesture:")
tap.delegate = self
self.view.addGestureRecognizer(tap)
}
// MARK: - UITapGestureRecognizer
func handleTapGesture(gesture : UITapGestureRecognizer) {
self.view.endEditing(true)
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
{
return true
}
I am wondering how to dismiss a key board if the user touches outside the UITextField. I am using Xcode 6.1. I added a UITextField to a UIViewController as per the below thru ViewDidLoad() function. Any help on dismissing the key board would be much appreciated.
class PickerdemoViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate{
var textBox1 : UITextField!
override func viewDidLoad() {
//..................adding text box.........................//
self.textBox1 = UITextField (frame: CGRectMake(100, 152.5, 50, 35))
textBox1.delegate = self
textBox1.backgroundColor = UIColor.whiteColor()
textBox1.placeholder = "enter"
textBox1.keyboardType = UIKeyboardType.DecimalPad
self.textBox1.resignFirstResponder()
textBox1.keyboardAppearance = UIKeyboardAppearance.Default
self.view.addSubview(textBox1)
super.viewDidLoad()
}
You need to have a reference to the UITextField so make a property value like this
class MyClass: UIViewController {
var textBox1: UITextField!
...
// create your textfield where ever you were by assigning it to self.textBox1
}
Then to dismiss the keyboard you resign its as the first responder.
self.textBox1.resignFirstResponder()
Update to dimiss keyboard
Dismissing on return/done with the textField delegate method
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.textBox1.resignFirstResponder()
return true
}
Dismissing on a button click (custom IBAction method)
#IBAction func buttonClicked(sender: UIButton!) {
self.textBox1.resignFirstResponder()
}
This will dismiss the keyboard by tapping screen. Make sure to not put it in the viewDidLoad.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { // this func lets you close keyboard by touching screen
self.view.endEditing(true) // this line lets you close keyboard by touching screen
}
I've been having some trouble with something I thought might be easy. I have a table in my root view controller, when a row is selected I push a new view and from there I go to another tab.
My question is how do I make sure that as soon as the user taps the first tab the navigation controller will pop to root?
Following delegate is called while each tab is selected on tabbar.
-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
Put following code inside this delegate method.
if ([viewController isKindOfClass:[UINavigationController class]])
{
[(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
}
its working fine on my app.
For Swift lovers:
import UIKit
class YourTabBarControllerHere: UITabBarController,
UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self;
}
func tabBarController(tabBarController: UITabBarController,
didSelectViewController viewController: UIViewController) {
if let vc = viewController as? UINavigationController {
vc.popViewControllerAnimated(animated: false);
}
}
}
Edit: Swift 3 update, thanks to #Justin Oroz for pointing that out.
In Swift 3.1
Add UITabBarControllerDelegate to your TabBar Class:
class YourClass: UITabBarController, UITabBarControllerDelegate {
After:
override func tabBar(tabBar: UITabBar, didSelectItem item:
UITabBarItem) {
let yourView = self.viewControllers![self.selectedIndex] as! UINavigationController
yourView .popToRootViewControllerAnimated(false)
}
What you are trying to do sounds a little bit odd. Have you read the Human Interface Guidelines on combining UINavigationControllers and UITabBarControllers?
However, what you need to do is detect the selection of the tab by setting a delegate for your UITabBarController and implementing the tabBarController:didSelectViewController: delegate method. In this method you need to pop back to the root view controller using UINavigationController's popToRootViewControllerAnimated: method.
Swift 5.1 Answer:
class YourTabBarName: UITabBarController, UITabBarControllerDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
{
if let vc = viewController as? UINavigationController
{ vc.popToRootViewController(animated: false) }
}
}
[self.navigationController popToRootViewControllerAnimated:NO];
Swift 4.2
The solution that works for me is to subclass the UITabBarController and add the two delegate functions as follows:
import UIKit
class MyCustomTabBarController: UITabBarController, UITabBarControllerDelegate {
var previousSelectedTabIndex:Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
self.previousSelectedTabIndex = tabBarController.selectedIndex
}
override func tabBar(_ tabBar: UITabBar, didSelect item:
UITabBarItem) {
let vc = self.viewControllers![previousSelectedTabIndex] as! UINavigationController
vc.popToRootViewController(animated: false)
}
}
Make sure you set animated to false otherwise you will get
Unbalanced calls to begin/end appearance transitions for the targeted ViewController
Try this.
class TabBarClass: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
let vc = self.viewControllers![selectedIndex] as! UINavigationController
vc.popToRootViewController(animated: false)
}
}
First, you should create subclass of UITabbarController and add Observer:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tabBar addObserver:self forKeyPath:#"selectedItem" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}
When tabbar is selected, We will process in method:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:#"selectedItem"] && [object isKindOfClass:[UITabBar class]]){
UITabBar *bar = (UITabBar *)object; // The object will be the bar we're observing.
// The change dictionary will contain the previous tabBarItem for the "old" key.
UITabBarItem *wasItem = [change objectForKey:NSKeyValueChangeOldKey];
NSUInteger was = [bar.items indexOfObject:wasItem];
// The same is true for the new tabBarItem but it will be under the "new" key.
UITabBarItem *isItem = [change objectForKey:NSKeyValueChangeNewKey];
NSUInteger is = [bar.items indexOfObject:isItem];
if (is == was) {
UIViewController *vc = self.viewControllers[is];
if ([vc isKindOfClass:[UINavigationController class]]) {
[(UINavigationController *)vc popToRootViewControllerAnimated:YES];
}
}
}
}
The UTabController suggests a different UX for letting a user "pop to root". When switching back to a tab, it keeps the full UINav stack from before. If they tap the bar item a second time (tapping the selected tab), only then does it pop to root. That's all automatic. Some apps, like instagram, allow a third tap to scroll to top.
I'd suggest sticking with the defaults as that's what users will be expecting.
The below had worked for me .This code in swift 3:
1> subclass UITabbarController and implement two below method with one iVAr:
class MyTabBarController: UITabBarController ,UITabBarControllerDelegate {
var previousSelectedTabIndex : Int = -1
}
2> set the tabbar delegate in viewdidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self // you must do it}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
self.previousSelectedTabIndex = tabBarController.selectedIndex
}
func tabBarController(_ tabBarController: UITabBarController,
shouldSelect viewController: UIViewController) -> Bool {
if self.previousSelectedTabIndex == tabBarController.selectedIndex {
let nav = viewController as! UINavigationController // mine in nav_VC
for vc in nav.childViewControllers {
if vc is YUOR_DESIRED_VIEW_CONTROLLER {
nav.popToViewController(vc, animated: true)
return false// IT WONT LET YOU GO TO delegate METHOD
}
}
}
return true
}
tabBarController.selectedIndex give you the selected tab
In tabBarController_shouldSelect_viewController method you can set your desired view controller with some easy calculation.
if you are not getting the above code play with both above method and you come to know how both working together
Use selected view controller to popToRootViewController. Basically you need to cast this instance.
Swift
((selectedViewController) as! UINavigationController).popToRootViewController(animated: false)
//
// I just added extra line so the scroll bar won't annoy you.
Xcode 11.5, Swift 5:
You don't need to use two delegate methods. Only one is enough:
extension CustomTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.viewControllers?.firstIndex(of: viewController) == tabBarController.selectedIndex,
let navigationController = viewController as? UINavigationController {
navigationController.popToRootViewController(animated: true)
}
return true
}
}
//create a tabbar controller class set it to your TabbarController in storyboard
import UIKit
class MyTabbarViewController: UITabBarController,UITabBarControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
{
if let vc = viewController as? UINavigationController
{ vc.popToRootViewController(animated: false) }
}
}
I set my left bar button of UINavigationController as edit button using the code
leftBarButton = self.editButtonItem;
I want to change some disable/enable properties of other buttons with respect to the edit button's click action.
How can i find whether the Edit button is pressed or not?
The edit button's action sends your view controller the setEditing:animated message. Override this in your subclass to perform other actions when entering or leaving edit mode.
Be sure to call the super implementation at the end to manage the rest of the transition to editing view.
So finally i got the solution...
-(void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
if(editing) {
//Do something for edit mode
}
else {
//Do something for non-edit mode
}
}
This method will be called with out changing the original behavior of self.editButtonItem button.
In Swift:
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
....
self.navigationItem.leftBarButtonItem = self.editButtonItem()
}
override func setEditing(editing: Bool, animated: Bool) {
// Toggles the edit button state
super.setEditing(editing, animated: animated)
// Toggles the actual editing actions appearing on a table view
tableView.setEditing(editing, animated: true)
}
In Swift you can follow the below methods:
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = editButtonItem()
}
override func setEditing(editing: Bool, animated: Bool){
super.setEditing(editing, animated: animated)
tableView.setEditing(editing, animated: true)
}
UIBarButtonItem *barBut=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(doSomething)];
self.navigationItem.leftBarButtonItem=barBut;
[barBut release];
.h
-(void)doSomething;
.m
-(void)doSomething{
NSLog(#"dooooooooooooo");
//ur stuff
}
updated:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
will be called
editButtonItem
Returns a bar button item that toggles its title and associated state between Edit and Done.
- (UIBarButtonItem *)editButtonItem
Discussion
If one of the custom views of the navigationItem property is set to the returned object, the associated navigation bar displays an Edit button if editing is NO and a Done button if editing is YES. The default button action invokes the setEditing:animated: method.
Availability
Available in iOS 2.0 and later.
See Also
#property editing
– setEditing:animated:
Declared In
UIViewController.h
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIViewController_Class/Reference/Reference.html
I have a very simple table and when tocuh a cell it opens a new view with one UITextfield. All I want is that the keyboard will automatically opens, without the user have to touch the UITextfield.
Its all done in Interface Builder, so I am not sure how I do this. I guess I need to set the focus at some point ?
Thanks
To cause the keyboard to show up immediately you'll need to set the text field as the first responder using the following line:
[textField becomeFirstResponder];
You may want to place this in the viewDidAppear: method.
Swift 3 & 4:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
textField.becomeFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
}
Prefer adding the first responder on the main thread -
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.textField.becomeFirstResponder()
}
This will come in handy when the view controller view is added as a subview.