Can I have a UISearchBar be its own .inputAccessoryView? - ios

I need simple text input to aid in data filtering. Ideally I'd like to keep a strong reference to a UISearchBar, and when the user taps "Search", then this searchBar would becomeFirstResponder() and I would set
self.searchBar.inputAccessoryView = self.searchBar
But that doesn't seem to work. The .searchBar is generally not in the view controller's view hierarchy, and is something I would just hope to attach to the keyboard.
Otherwise I'll think of another approach. Ultimately I'm just trying to have text input that I can see while editing, and that should be attached to the toolbar. Ideally with an .inputAccessoryView so I don't have to bother with keyboard notifications / animations
Does anyone know if this is possible?

If I understand you correctly, you want to use the search bar both for triggering a keyboard and for showing the search term entered by the user, but do not want to always have the search bar on-screen but have it activated via a "Search" button.
That's not possible with a single UISearchBar, but you can just use two of them:
Add one as subview to your view controller and hide it (bar1), and use the second as inputAccessoryView (bar2); you should become delegate of both search bars.
When the user presses the "Search" button make bar1 become first responder, handle its events via the delegate protocol, and update the bar2 accordingly.
Prevent the user from directly entering text in bar2 by blocking it
with the shouldChangeTextIn delegate method. Other events that are
received in bar2 could be forwarded to bar1 where this makes sense for you.
To get you started, here's some code for the basic setup (which would go in e.g. viewDidLoad):
self.dummySearchBar = UISearchBar()
dummySearchBar.isHidden = true
dummySearchBar.delegate = self
self.visibleSearchBar = UISearchBar()
visibleSearchBar.delegate = self
dummySearchBar.inputAccessoryView = visibleSearchBar
Then, in your "Search" button handler, let the keyboard with the attached search bar appear like this:
dummySearchBar.becomeFirstResponder()
Note: I have a similar setup in a project but for simplicity I use UITextFields instead of UISearchBars; still, I think the basic approach should work with UISearchBars as well.

add toolBar to searchBar
searchBar.inputAccessoryView = toolBar
hide keyboard
searchBar.endEditing(true)

Related

Prevent keyboard from dismissing while changing views

On apps like say the stock messages app, if you’re in a conversation with the keyboard showing and swipe to go back to your conversation list, the keyboard remains up as the view gets swiped away.
I can’t seem to figure out how to mimic this behavior but I’ve seen it in other apps so it’s gotta be possible.
Edit: Not sure I understand why this is getting downvotes. It’s definitely a valid question where I couldn’t find the answer on google?
Edit 2: Here’s a video of what I’m trying to accomplish https://arxius.io/v/a555c8db compared to this behavior in discord https://arxius.io/v/0bfda09a
On apps like say the stock messages app, if you’re in a conversation with the keyboard showing and swipe to go back to your conversation list, the keyboard remains up as the view gets swiped away.
I don't actually see that behavior, at least in the Messages app on an iPhone. That said, the keyboard should remain visible whenever the first responder can accept text. If you want to switch to a different view controller and keep the keyboard visible, then make sure that first responder in the new view graph is editable. For example, if there's a text field, you could set it to be the first responder.
So before we talk about any kind of solution, let's learn exactly why the keyboard is dismissed.
As you know, iOS UI works on a view controller based system, with a text field ultimately being managed by a view controller somewhere.
When you click the back button, the active view controller is released from the navigation stack and therefore the system deduces that the text field is no longer in use, so it resigns it as the first responder.
Unfortunately there is no built in way to alter this behaviour and whilst we can speculate how apple might do it, we do not know.
The few options we have are not particularly neat or tidy, but a method I have had success with in the past is creating a hidden text field directly on the window before you pop the view controller and setting it first responder. Then on your other view controller, the text field can take first responder from the invisible one and remove it.
This is not ideal, but it's the only technique that comes to mind.
It is correct that you had to have UITextFiled available for both views to have keyboard passed between them consistently. But nobody said that this textfield had to be on screen, or had to be part of ViewController's view.
So all you had to do is to place this textFiled somewhere out of screen, for example as subview of your window, or NavigationController's view, make it first responder, and switch to your text field on view didAppear:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.textField.becomeFirstResponder()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
let fixedView = self.view.window
let fakeTextField = fixedView?.subviews.last as? UITextField ?? UITextField()
fakeTextField.autocapitalizationType = textField.autocapitalizationType
fakeTextField.autocorrectionType = textField.autocorrectionType
fakeTextField.center = CGPoint(x: -100, y: -100)
fixedView?.addSubview(fakeTextField)
fakeTextField.becomeFirstResponder()
}
Make sure that keyboard configuration is the same, otherwise you will have it switching.

Saving searches from searchBar

I have a UISearchController set up in my table VC and works as expected.
However, I want to be able to save the text from searches (i.e. after they press 'search' or 'enter' on keyboard) into an array.
I couldn't find anything relevant here https://developer.apple.com/documentation/uikit/uisearchbar?language=objc and suspect the solution will involve stuff with the keyboard...
You need to implement searchBarSearchButtonClicked: and/or searchBarTextDidEndEditing: on your searchBar's delegate. These method are called whenever the user presses the search button or finishes editing the text in the search bar, respectively
There is delegate:
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar;
Inside this delegate method add searchBar.text into your desired array.

How to trigger the "cancel search" when using only a UISearchBar?

I have a table view with a header that displays a UISegmentedControl and a UISearchBar. Keep in mind that I am not using a UISearchController. When I have searched the current list, and I toggle a different segment, I want to cancel the search and reload the list with the new data.
Currently I am manually clearing the search text, animating the cancel button and hiding the keyboard. But I am also doing that inside my searchBarCancelButtonClicked method.
Is there a way to programmatically cancel the search (clearing the text, hiding the keyboard, and hiding the cancel button) when only using a UISearchBar?
No, there's no way to automatically clear the text field, hide the keyboard, etc. Even though it seems like common functionality, it's up to each developer to decide how to implement it. Apple just provides the ability to catch the event when the user taps the Cancel button.
Typically, I'll create a local function in the view controller like:
-(void)clearSearchBar:(UISearchBar *)searchBar {
searchBar.Text = #"";
[searchBar resignFirstResponder];
...
}
Then, in searchBarCancelButtonClicked: (assuming you've created an IBOutlet for the search bar), you can do this:
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self clearSearchBar:self.searchBar];
}
You can then also call clearSearchBar: anywhere else you need to clear it.
Obviously, there's room to use categories here to avoid duplicating code.
You could also just call searchBarCancelButtonClicked: like this:
[self.searchBar.delegate searchBarCancelButtonClicked:self.searchBar];

Swap out a custom inputView for the standard keyboard in iOS

I have a custom inputView for a particular textfield, and it works well. However, I cannot discern how to dismiss the view and get the regular keyboard back. (I have a SWAP button right next to the TextField.) I tried setting the textfield's inputView to nil, but that did nothing.
I do not need a full custom keyboard, but I need more than an Accessory view above the keyboard, which is why I am trying this route. I need about 20 custom buttons in addition to the regular keyboard, and I do not like the idea of a huge Accessory view taking up so much space.
I also would rather not require the user to initially install a full custom keyboard before being able to use the app.
Thank you very much for any suggestions.
I think you will probably have to do this:
Call resignFirstResponder on the UITextField
After the animation finishes, set your inputView to nil
Call becomeFirstResponder on the text field
The keyboard animation duration is sent in the userInfo dictionary on the keyboard presentation notifications.
In addition to the accepted answer, you can use reloadInputViews() (and this is less likely to suffer any animation glitches resulting from the resignFirstResponder, becomeFirstResponder calls):
yourTextField.inputView = nil;
yourTextField.reloadInputViews();
Here's more info in the Apple's Docs.

Attaching a custom alert view above the iOS keyboard

I'm trying to design (a "properly designed," not "hack") custom alert view. The view should attach itself to the top of the keyboard; sliding up with the keyboard (if there is an alert) or being hidden (if there is no alert).
The view should always "stick" to the keyboard... including, for instance, when the keyboard hides. In that case, the view should slide right down, out of sight, along with the keyboard.
Here's an example of what I'm trying to achieve (with an active alert):
I have originally thought about subclassing UIAlertView, but it looks like that is not recommended. And, after experimenting a bit, this is clearly a tricky task. I've got an alert that shows up but, it turns into problems staying in sync with the keyboard, and I haven't found a way to make it "track" with the motion of the keyboard... not smoothly.
Any ideas?
You can achieve this with inputAccessoryView of UITextField and UITextView. See Custom Views for Data Input chapter in Apple's "Text Programming Guide for iOS" for more information.
For example, a very simple red bar above the keyboard can be added with the following code:
let keyboardAlertView = UIView(frame:CGRectMake(0,0,320,44))
keyboardAlertView.backgroundColor = UIColor.redColor()
textField.inputAccessoryView = keyboardAlertView

Resources