UISearchBar select all text - objective-c

Is there any way to select all text in UISearchBar?
I tried [searchBar selectALL:], but it throw the signal (unrecognized selector).
I want to allow user to alter previous search text. At the some time, when user just starts typing new request, the old one should be dismissed. The standard way how to achieve it - select all text at the moment when text begin editing.

This can be accomplished using the standard UIResponder semantics. No need to dig down into the private view hierarchy of UISearchBar.
[[UIApplication sharedApplication] sendAction:#selector(selectAll:) to:nil from:nil forEvent:nil]
You can call this from anywhere, and the selectAll: selector will run the responder chain to see if any objects respond to it. Assuming your search bar is currently the first responder (if the user is typing in it), it will respond and the result will be all text selected. If not you can make it the first responder by calling becomeFirstResponder on the search bar.
[_mySearchBar becomeFirstResponder]
[[UIApplication sharedApplication] sendAction:#selector(selectAll:) to:nil from:nil forEvent:nil]

If you want the 'type to replace' functionality that selecting the text in the UITextField gives you (ie the extra tap on the cross is unacceptable), you can dig through the subviews of the UISearchBar to find the UITextField (or UISearchBarTextField) and select its text:
// need to select the searchBar text ...
UITextField * searchText = nil;
for (UIView *subview in searchBar.subviews)
{
// we can't check if it is a UITextField because it is a UISearchBarTextField.
// Instead we check if the view conforms to UITextInput protocol. This finds
// the view we are after.
if ([subview conformsToProtocol:#protocol(UITextInput)])
{
searchText = (UITextField*)subview;
break;
}
}
if (searchText != nil)
[searchText selectAll:self];

In my case, the sending selectAll(_:) didn't work immediately after calling becomeFirstResponder.
I worked around it by waiting one runloop:
Swift 2:
dispatch_async(dispatch_get_main_queue()) {
UIApplication.sharedApplication().sendAction(#selector(UITextField.selectAll(_:)), to: nil, from: nil, forEvent: nil)
}
Swift 3:
DispatchQueue.main.async(execute: {
UIApplication.sharedApplication().sendAction(#selector(UITextField.selectAll(_:)), to: nil, from: nil, forEvent: nil)
})

Here is another suggestion: when someone activates the search bar, there are two possible intentions: type new text or add to the existing text. I think you should give your user the choice.
If he wants to add text he naturally taps again at the end of the existing text.
If he wants to start over, he can press the clear button that automatically appears when the search bar becomes active.

Swift 4
If you want to select all text when searchBar become first responder.
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
DispatchQueue.main.async {
UIApplication.shared.sendAction(#selector(UITextField.selectAll(_:)), to: nil, from: nil, for: nil)
}
return true
}

I dont think there is a method to select all text. Maybe when there is a focus on UISearchBar you can clear the search bar like so - searchBar.text = #""
i.e. clear text in the search bar... Hope this helps in some way...

You can accomplish this by keeping a BOOL indicating if editing the search bar text field just started. Then, you can catch the first key press in the searchBar delegate methods.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
firstEdit = YES;
}
- (BOOL)searchBar:(UISearchBar *)searchBar
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text {
if (firstEdit) {
searchBar.text = text;
firstEdit = NO;
}
return YES;
}

Related

Moving Onto The Next UITextField When 'Next' Is Tapped

I have an iPad application which has a sign up form within it. The form is very basic and contains only two UITextFields which are for Name & Email address.
The first TextField is for the candidates Name, When they enter their name in and press 'Next' on the keyboard I want this to automatically move to the next Email Address TextField to editing.
Any idea how I can set the next button the keyboard to jump to the next keyboard?
Thanks
You need to make your view controller the UITextField delegate, and implement the UITextField delegate method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == nameField) {
[textField resignFirstResponder];
[emailField becomeFirstResponder];
} else if (textField == emailField) {
// here you can define what happens
// when user presses return on the email field
}
return YES;
}
Swift version:
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == nameField {
textField.resignFirstResponder()
emailField.becomeFirstResponder()
} else if textField == emailField {
// here you can define what happens
// when user presses return on the email field
}
return true
}
You may also want to scroll your view for the emailField to become visible. If your view controller is an instance of UITableViewController, this should happen automatically. If not, you should read this Apple document, especially Moving Content That Is Located Under the Keyboard part.
Additionally to #lawicko 's answer I often change the button text to give that final finishing touch (e.g. says next when there are more fields and then done when on the last):
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
BOOL isLastTextField = //.. your logic to figure out if the current text field is the last
if (isLastTextField) {
textField.returnKeyType = UIReturnKeyDone;
} else {
textField.returnKeyType = UIReturnKeyNext;
}
}
Swift version of correct answer.
In my experience, you do not need to resignFirstResponder when switching textFields.
In this example, it's just your basic username and password textFields.
The keyboard "return key" in storyboard for username is set to "Next" and the one for password is set to "Done".
Then just connect the delegates for these two text fields and add this extension and you're pretty much done.
extension LoginViewController: UITextFieldDelegate {
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == textFieldPassword {
self.view.endEditing(true)
} else {
textFieldPassword.becomeFirstResponder()
}
return true
}
}
A more consistent and robust way is to use NextResponderTextField
You can configure it totally from interface builder.
All you need to do is
Set the class type of your UITextField to be NextResponderTextField
Then set the outlet of the nextResponderField to point to the next responder it can be anything UITextField or any UIResponder subclass. It can be also a UIButton and the library is smart enough to trigger the TouchUpInside event of the button only if it's enabled.
Here is the library in action:
A Swift 4 extension. Just pass the array of UITextFields and it will connect each one to the next until the last one which resigns the first responder (hides the keyboard):
extension UITextField {
class func connectFields(fields: [UITextField]) {
guard let last = fields.last else { return }
// To reset the targets in case you call this method again to change the connected fields
fields.forEach { $0.removeTarget(nil, action: nil, for: .editingDidEndOnExit) }
for i in 0 ..< fields.count - 1 {
fields[i].returnKeyType = .next
fields[i].addTarget(fields[i + 1], action: #selector(UIResponder.becomeFirstResponder), for: .editingDidEndOnExit)
}
last.returnKeyType = .continue
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), for: .editingDidEndOnExit)
}
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.textFieldName)
{
[self.textFieldName resignFirstResponder];
[self.textFieldPassword becomeFirstResponder];
}
else if (textField == self.textFieldPassword)
{
[self.textFieldPassword resignFirstResponder];
[self login:self];
}
return true;
}
#interface MLLoginViewController ()<UITextFieldDelegate>
#end
#implementation MLLoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.textFieldName.delegate = self;
self.textFieldPassword.delegate = self;
Make an outlet for the textfield, then
viewController.h
(IBAction)textFieldDoneEditing:(id)sender;
viewController.m
(IBAction)textFieldDoneEditing:(id)sender {
[textField resignFirstResponder];
if (textField == nameField) {
[emailField becomeFirstResponder];
}
}
Make the relation between (show the connections inspector > Sent Events)didEndOnExit and textFieldDoneEditing

UITextField editingChange Control Event not works

I have some textfields and I want to do when I change textfield1 text set text to other textfields. My code below. But it not works. How can I solve this?
- (IBAction)TCKimlikTextChange:(id)sender {
[TCKimlikText addTarget:self action:#selector(yourMethod: ) forControlEvents:UIControlEventEditingChanged];
}
-(void)yourMethod: (UITextField*)tf_{
if (tf_) {
if (TCKimlikText.text == #"1") {
AdinizText.text = #"Hacer";
}
}
}
Your code is very abstract. yourMethod, tf_ TCKimlikTextChange are all expressions that are not very human readable. You should work on your variable names.
I suppose your first method is a button handler. It just assigned a target and action to the text field, but does not call any method. You do not need that action if you use the delegate protocol.
To solve your problem: implement the UITextField delegate methods. Make sure you set the delegate (probably self) for your text fields. Your view controller must mention the <UITextFieldDelegate> protocol in its .h file. Thus, in textField:shouldChangeCharactersInRange:replacementString::
if ([textField.text isEqualToString:#"1"]) {
displayLabel.text = #"Hacer";
}
Notice that you need isEqualToString: to compare strings, a simple == won't do.
If u are want to change on the click of the return button use the delegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField == field1)
[field2 setText:field1.text];
[field1 resignFirstResponder];
return YES;
}
or u can use other delegates too like:
– textFieldShouldBeginEditing:
– textFieldDidBeginEditing:

Obj C - resign first responder on touch UIView

I'm trying to get the keyboard to disappear when the screen is touched, a question that is answered all over stackoverflow. I was able to get the keyboard to disappear when the enter key was pressed thanks to a thread here. I'm not having luck on the background touch resigning the first responder. The method is being entered, I have an NSLog in the method saying, "in backgroundTouched" but the keyboard is still there.
I've tried making the UIView a UIControl class so I could use the touch event.
journalComment is a UITextView.
-(IBAction)backgroundTouched:(id)sender
{
[journalComment resignFirstResponder];
NSLog(# "in backgroundTouched");
}
I've also tried having a invisible button under everything that calles the backGroundTouched method. I think it maybe that I'm missing something in interface builder, but I'm not sure what.
Thank you for any help!
This is what works for the done button:
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
// Any new character added is passed in as the "text" parameter
if ([text isEqualToString:#"\n"]) {
// Be sure to test for equality using the "isEqualToString" message
[textView resignFirstResponder];
// Return FALSE so that the final '\n' character doesn't get added
return FALSE;
}
// For any other character return TRUE so that the text gets added to the view
return TRUE;
}
I found the following code works best with my text view (not text field) without the delegate methods:
first you set up a tap gesture recognizer onto your view :
- (void)viewDidLoad{
UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(tap:)];
tapRecognizer.delegate = self;
[self.view addGestureRecognizer:tapRecognizer];
}
and then in your tap method :
- (void)tap:(id)sender
{
// use to make the view or any subview that is the first responder resign (optionally force)
[[self view] endEditing:YES];
}
this should allow your keyboard to be dismissed when you anywhere on the view.
Hope this helps
Try this. We had this problem eariler, but eventually found the right solution.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[yourtextfield resignFirstResponder];
// you can have multiple textfields here
}
This should resolve the problem with the keyboard not dissapearing when pushing the background.

Cocoa : How to make multiline NSTextField?

How to make multiline NSTextField? UPDATE: I've found in IB special type of NSTextField called "Wrapped Text Field". It is multiline but when I want get a newline I have to press Ctrl+Enter. But I want to press only Enter to get a newline. How can I do it?
There is no way to specify this behavior solely in Interface Builder. You can do it with a delegate message as described in this tech note QA1454.
Here is the example delegate message from the tech note:
- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
{
BOOL result = NO;
if (commandSelector == #selector(insertNewline:))
{
// new line action:
// always insert a line-break character and don’t cause the receiver to end editing
[textView insertNewlineIgnoringFieldEditor:self];
result = YES;
}
else if (commandSelector == #selector(insertTab:))
{
// tab action:
// always insert a tab character and don’t cause the receiver to end editing
[textView insertTabIgnoringFieldEditor:self];
result = YES;
}
return result;
}
Using NSTextView, its a multiline NSTextField sorta, it is a subclass of NSText correct my if I am wrong. The NSTextView has an NSTextStorage, which is a subclass of NSAttributedString. You need to give it an NSAttributedString object instead of a NSString to fill its contents as it can display colors etc.
[[yourTextView textStorage] setAttributedString:attrStr];

call a method with the "Return" (Done) Button of the keyboard

is there anyboby who can give me an example method that is called by pressing the return button of the keyboard and saves the text of a textview (that was typed in before) in the nsuserdefaults?
thanks a lot :)
Make sure your UITextField has a return key type set to UIReturnKeyGo (this is for the image on the keyboard):
theTextField.returnKeyType = UIReturnKeyGo;
Then use this method to do what ever you want to do:
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
// Tell the keyboard where to go on next / go button.
if(textField == theTextField)
{
// do stuff
}
return YES;
}
To get the text from the textfield just call theTextField.text and save as you wish!
Swift Version
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Tell the keyboard where to go on next / go button.
if textField == theTextField {
// do stuff
}
return true
}
If you are adding UITextField to an UITableCell dynamically, you need to also set delegate for it:
self.textfield.delegate = self;
also on the the header file you need to add this:
#interface YourController: UIViewController <UITextFieldDelegate>