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.
Related
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.
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];
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.
In MFMailComposeController, once we start typing, the list of email addresses is shown. Once we select, the TextField displays the name of the user with a small Oval background. Then we can continue typing. If we want to delete it, then pressing backspace selects the oval background and on second backspace the email address is deleted. How can this be implemented.
I am not interested in the search part. I am fine with Implementing it. But I am more interested in getting the TextField working as in the MFMailComposeController. The way the blue oval background is set for already typed in emails.
Thanks
If you simply want to search through a set addresses,strings or whatever you can implement UISearchDisplayController and you will getyour job done.Here's the link on UISearchDisplayController iPhone.
Else , if you want to have youown you have will have to have a UITextField with a UITableView and you will have to implement the delegates method of UITextField to get the autocomplete feature searching through tableview's datasource.Implement your logic using delegates of UITableView and UITexField.
you can use many open source implementation one name from them is TITokenFieldView.
This is one of those "it was working a while ago" troubleshooting efforts.
I'm working on the document preview view controller, in which is a scroll view, which itself contains subclasses of UIView that represent each document. I'm modeling this pretty closely to how Keynote handles its document preview, except I build my scroll view horizontally and with paging. But the standard user experience is present: Long press on a document icon causes all document icons to start jiggling, nab bar has + button and Edit button, etc.
The issue at hand is that when you tap on the name of a document, I hide all the others, move the one being edited front and center, build a new text edit field, add it as a subview atop the real name label, and set it as first responder; but the
[editNameTextField setClearButtonMode:UITextFieldViewModeWhileEditing];
while correctly showing in the edit field is not taking any action when the user taps on the clear button.
I can't figure out what I may have done to cause this to not work -- it had been!
My first thought was that somehow my instance of this subclass is no longer the delegate for this text edit field. To try and confirm/deny that, I usurped a tap on the image view of the document preview to compare the delegate property to self, and it passes.
if (editNameTextField) {
NSLog(#"editNameTextField is still active");
if ([editNameTextField.delegate isEqual:self]) {
NSLog(#"we're still the delegate for the editNameTextField");
}
}
Editing the text within the edit field works fine. Pressing the Return/Done key correctly sends the delegate message textFieldShouldReturn:
While investigating this I implemented the delegate method textFieldShouldClear: just to write a log message if the method gets called (and return YES of course). It never gets called.
My next thought was that perhaps a subview had covered up the area where the clear button sits. So I implemented textFieldShouldBeginEditing: and used the opportunity to bring my the text field to the front. That didn't change anything either. I set a debugger breakpoint there to play a sound when it was called, and it got called, so I know my text edit field is frontmost.
I have only one troubleshooting strategy remaining: Go backwards through snap shots until it starts working again. Before doing that I thought I'd see if any of the more experienced folks out here have any suggestions of what to try next.
Where are you adding the textfield? As a subview of the scrollView? If you added the textfield and it is out of bounds of its parent view it won't receive any touches.
You can try and not call becomeFirstResponder and see if clicking it will show keyboard. Another possible error might be that the parent view of the UITextField has userInteractionEnabled = NO.
Without seeing more code I'm afraid I can not offer more solutions.