41

I have a textfield with a hidden keyboard (since I'm using it with bluetooth). However, in iOS9 the shortcut bar keeps appearing.

Is there a way to hide it too?

Thank you so much!

TenaciousJay
  • 6,750
  • 3
  • 45
  • 48
Jordi Puigdellívol
  • 1,710
  • 3
  • 23
  • 31

8 Answers8

64

You can pass your textfield name in place of userNameTextField for which you want to remove shortcut bar.

UITextInputAssistantItem* item = [userNameTextField inputAssistantItem];
item.leadingBarButtonGroups = @[];
item.trailingBarButtonGroups = @[];
Dheeraj Singh
  • 5,143
  • 25
  • 33
  • Yes, prefix with an `is_grater__or_equal_than(9.0)` or it will crash in lower versions – Jordi Puigdellívol Sep 27 '15 at 16:30
  • @Dheeraj - how would this be done in Xamarin.iOS C# code? Within that framework, InputAssistanceItem appears to be read-only (http://stackoverflow.com/questions/37442203/xamarin-ios-remove-shortcut-bar-from-picker) – jbyrd May 25 '16 at 17:41
  • Please can any one tell me where we need to use this 3 lines – S P Balu Kommuri Jun 03 '16 at 05:45
  • @Balu u can put this code in anywhere and make a call to it before the textfield is edited. – Dheeraj Singh Jun 03 '16 at 14:03
  • @DheerajSingh thank you. My issue was resolved. I'm using this - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO]; }]; return [super canPerformAction:action withSender:sender]; } – S P Balu Kommuri Jun 07 '16 at 08:11
  • For me, this broke text input via a Bluetooth keyboard on the affected textfields – lundhjem Oct 04 '16 at 18:39
  • 2
    Running Leaks Instrument seems to indicate this code leaking all over the place. – lundhjem Mar 13 '17 at 19:05
  • I'm also seeing leaks when doing this. – Eagle11 Mar 27 '17 at 13:44
  • 1
    Note that, as it says [here](https://developer.apple.com/documentation/uikit/uitextinputassistantitem), the `autocorrectionType` must be set to `.no` too, otherwise it will still show the suggestions – Daniel Aug 11 '17 at 17:05
15

In Swift 2.0

if #available(iOS 9.0, *) {
    let item : UITextInputAssistantItem = yourTextView.inputAssistantItem
    item.leadingBarButtonGroups = []
    item.trailingBarButtonGroups = []
} else {
  // Fallback on earlier versions
}
TenaciousJay
  • 6,750
  • 3
  • 45
  • 48
OverD
  • 2,612
  • 2
  • 14
  • 29
  • Just FYI, you need to call this on every UITextView or UITextField (basically anything that pops up the keyboard) as each input field has it's own UITextInputAssistantItem. – TenaciousJay Sep 29 '15 at 14:00
10

I had the same issue. And so starts a search of SO. So the above helped me out, but the whole, "if iOS9 thing" might be best framed like this:

if ([self respondsToSelector:@selector(inputAssistantItem)]) {
    // iOS9.
    UITextInputAssistantItem* item = [self inputAssistantItem];
    item.leadingBarButtonGroups = @[];
    item.trailingBarButtonGroups = @[];
}

Happily, I'd created a sub-class of a UITextField, (CHTextField) and was in use everywhere. So it was a very easy fix to whack this in the over-ridden "init" method.

Hope it helps.

Carl Hine
  • 1,817
  • 18
  • 24
9

Alternatively, just create an extension for UITextField in Swift 2.0 like this.

extension UITextField
{
    public func hideAssistantBar()
    {
        if #available(iOS 9.0, *) {
           let assistant = self.inputAssistantItem;
            assistant.leadingBarButtonGroups = [];
            assistant.trailingBarButtonGroups = [];
        }
    }
}

Then you can just call hideAssistantBar() on any text field you like.

@IBOutlet weak var myTextField: UITextField?;

override public func viewDidLoad() {
    super.viewDidLoad();

    myTextField?.hideAssistantbar();
}
Jacob Joz
  • 732
  • 1
  • 11
  • 29
7

In Swift 3.0 and 4.0

self.textField.inputAssistantItem.leadingBarButtonGroups.removeAll()
self.textField.inputAssistantItem.trailingBarButtonGroups.removeAll()
Pranavan SP
  • 1,785
  • 1
  • 17
  • 33
5

An easy way to do this for all text fields in your app is to create a category on UITextInputAssistantItem and override the getters for leadingBarButtonGroups and trailingBarButtonGroups like this:

@implementation UITextInputAssistantItem (RemoveBars)

- (NSArray<UIBarButtonItemGroup *> *)leadingBarButtonGroups
{
    return @[];
}

- (NSArray<UIBarButtonItemGroup *> *)trailingBarButtonGroups
{
    return @[];
}

@end

This worked for me on iOS 9.x and 8.x, no need for any conditional code.

Be careful with this though, this overrides those properties for EVERYTHING that uses UITextInputAssistantItem

jere
  • 4,306
  • 2
  • 27
  • 38
4

Just to expand on the other answers here. I cobbled together some Swift 2.0 code that will loop through all subviews of a given view and disable the UITextInputAssistantItems for all UITextFields and UISearchBars.

func hideTheAssistantBar(view:UIView) {
    //Check this view
    for case let textField as UITextField in view.subviews {
        let item : UITextInputAssistantItem = textField.inputAssistantItem
        item.leadingBarButtonGroups = []
        item.trailingBarButtonGroups = []
    }
    for case let searchBar as UISearchBar in view.subviews {
        let item : UITextInputAssistantItem = searchBar.inputAssistantItem
        item.leadingBarButtonGroups = []
        item.trailingBarButtonGroups = []
    }

    //Now find this views subviews
    let subviews = view.subviews

    for subview : AnyObject in subviews {
        if subview.isKindOfClass(UIView) {
            hideTheAssistantBar(subview as! UIView)
        }
    }
}

You can then call this function passing in whatever view you would like to start at. I call this inside of my ViewDidLoad() method and pass in self.view like hideTheAssistantBar(self.view).

I actually went a step further for my needs and added this function to a helper class I use for common code. Therefore inside of my viewDidLoad() function I actually just call helper.hideTheAssistantBar(self.view) and then I don't have to put that function in every file.

Hope this helps someone coming along looking for an easy way to remove the assistant bar from all UITextFields and UISearchBars in one fail swoop.

Thanks to @Arkader for the swift code to recursively find all subviews. Swift List Subviews

Community
  • 1
  • 1
0

Just to build on what Pranavan posted because setting the bar button groups to an empty array doesn't seem to work in iOS 12 or 13 using Xcode 11.

let inputAssistantItem = textFieldForTypingText.inputAssistantItem
inputAssistantItem.leadingBarButtonGroups.removeAll()
inputAssistantItem.trailingBarButtonGroups.removeAll()

I placed the above code in the viewDidLoad() function.

You can also give the option to the user:

inputAssistantItem.allowsHidingShortcuts = true

In the case letting the user hide it, if the text field becomes first responder again, they'll have to hide it again.

hoptown
  • 65
  • 7