Saving searches from searchBar - ios

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.

Related

Can I have a UISearchBar be its own .inputAccessoryView?

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)

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];

iOS keyboard flickers when switching view controllers

I have a registration form and I want to have the keyboard always on top.
The way I'm doing it now, is that when the user moves between view controllers, in viewDidLoad, the first UITextField becomes the first responder.
The problem is that the keyboard flickers (disappears and then appears again) when the user moves between view controllers.
Also, related to this: I have a form with a few uitextfields. When the user presses next it goes to the next uitextfield using becomefirstresponder. When the user is in the last textfield, the keyboard button becomes "Done". Then, when the user presses it, if there's an error with the last field, it should get the focus (calls becomeFirstResponder) but that doesn't happen (nothing get's the focus and the keyboard goes down). All the other fields get the focus fine, just this last field doesn't. I've tried about everything: switching to other textfields and back. The problem is that done automatically removes the keyboard.
You should have made two separate questions for this.
First, your flickering:
I'm guessing you're using a UINavigationController. You can add an invisible UITextField somewhere in the UINavigationController, which you give focus before you switch to a new ViewController. Then, when the new ViewController has appeared (viewDidAppear), set the focus to the first textField as you want.
However, the entire approach is kind of hackey and I don't recommend you use it. Instead, try using several views in a scrollView, of which you change the offset when you move to the new view. This will also solve the flickering.
Second, losing firstResponder status on Done:
The done button is specifically there to indicate exactly that which it says; Done. Pressing this assumes the user is finished and that no text is left to type, thus dismissing the keyboard.
If you really want to keep the Done button, then try the following;
Allow the user to dismiss the keyboard.
Upon dismissal, check for the error in the last field.
If there is an error, instead of calling [lastField becomeFirstResponder], try [self performSelector:#selector(thisSelectorWillCallFirstResponder) withObject:nil afterDelay:1.0].
In the method thisSelectorWillCallFirstResponder call [lastField becomeFirstResponder].
This will give time for the keyboard to disappear, before making it pop up again, so it doesn't interfere with the becomeFirstResponder call.
Another method would be to not use a Done button, but instead use the return key. You can intercept return anytime with the delegate method textFieldShouldReturn:. There you can handle any error checking, without causing the textField to lose its focus.

resignfirstresponder on a UITextView inside a UITableViewCell

I am hoping if someone can help me resolve an IOS/XCode question.
I need to have a UITextView created inside a UITableViewCell, this UITextView has responds to a user click, upon which a UIPopoverController will be displayed so that a sub-UITableView is displayed (inside the UIPopoverController) allowing a user to select from a list of choices (lines of text). After the user select the choice (one of the line of text), that line of text will then be displayed inside the said UITextView. First problem I am having is that when the user click on the UITextView the keyboard gets displayed instead of the UIPopoverController. How do I go about disabling ie. calling resignFirstResponder so that instead of the keyboard displaying, I get the UIPopoverController coming up instead. Would someone be kind enough to share similar codes? or point me to some sample of how this can be done? Thanks so much in advance.
You can use following delegate method to detect when textView is tapped and show your popOverController accordingly, return 'NO' in the delegate method so that no keyboard will appear...
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
// code to show popOverController
return NO;
}

Getting notified when user presses "Search" on keyboard in UISearchDisplayController

I am using a UISearchDisplayController to let the user search through a list of buildings on a university campus. Sometimes, the user will know exactly what building they want, enter the building's number, and that building will then be the only building result showing in the UITableView. At the moment, if the user proceeds to hit "Search" on the keyboard, the keyboard animates off the screen and the user then has to make a second tap on the sole item in the UITableView to be sent to a point on a map showing the location of that building.
My question is, is there a way to be notified when the user hits the "Search" button on the keyboard inside a UISearchDisplayController, so that I can perform a check to see if there's only one result, and if so, take the user straight to that result, rather than requiring them to explicitly make the second tap? I've looked at the methods provided by the UISearchDisplayDelegate, but can't see anything relevant.
UISearchDisplayController has a UISearchBar, you can set a delegate for search bar and implement -searchBarSearchButtonClicked:.
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
}
This also works with the keyboard search button.

Resources