UItextView and back space click event on keyboard - ios

I want to detect which character is removed on back space click event on keyboard in UITextView.
So if anybody knows solution please help.
Thanks in advance.

you should implement the protocol UITextViewDelegate method
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
and just get the text in range
try this to have a log (it's empty in case it's not a replacement but a new input)
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSLog(#"deleting this string: |%#|", [textView.text substringWithRange:range]);
return YES;
}
ps
remember to set your class as the delegate of your UITextView

Here's what you want. This method detects whenever a character is removed, and prints it to the console.
#interface ViewController ()<UITextFieldDelegate>
{
UITextField *textField;
NSString *currentText;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 50, self.view.frame.size.width-40, 30)];
[textField addTarget:self action:#selector(textChanged:) forControlEvents:UIControlEventEditingChanged];
textField.delegate = self;
textField.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:textField];
}
-(void)textChanged:(UITextField *)sender{
if (!currentText) {
currentText = sender.text;
}
if (![currentText isEqualToString:sender.text]) {
//The text that is in the textField at the moment is shorter than it was the last time the textfield was editted... This shows that a backspace was pressed
if (currentText.length > sender.text.length) {
NSLog(#"Character: %#", [currentText substringFromIndex:sender.text.length]);
}
}
currentText = sender.text;
}
#end

Related

Keyboard not showing for UITextView after hiding it using [self endEditing:YES]

I have a UITextView that is created programmatically on viewDidLoad using the method below. Keyboard is shown successfully right after [_answerTextView becomeFirstResponder] is called. And hid if the user enters return(\n) character.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[self endEditing:YES];
return NO;
}
return YES;
}
After the keyboard is hid by the code above, I'm not able to bring it back anymore by tapping the UITextView again.
I tried showing the keyboard by calling [_answerTextView becomeFirstResponder] on Tap event for the parent UIView and it worked. But that's not what I want.
UITextView is created by the method below;
-(UITextView*)createSurveyTextView{
_answerTextView = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, _optionsStackView.frame.size.width, 200)];
_answerTextView.keyboardType = UIKeyboardTypeDefault;
_answerTextView.text = #"";
_answerTextView.editable = true;
_answerTextView.selectable = true;
_answerTextView.delegate = self;
[_answerTextView becomeFirstResponder];
_answerTextView.backgroundColor = [UIColor whiteColor];
_answerTextView.textColor = [UIColor blackColor];
_answerTextView.layer.cornerRadius = 5;
[_optionsStackView addSubview:_answerTextView];
_answerTextView.font = [UIFont systemFontOfSize:20];
[_answerTextView setReturnKeyType:UIReturnKeyDone];
[_optionsStackView bringSubviewToFront:_answerTextView];
[self bringSubviewToFront:_answerTextView];
[_answerTextView setUserInteractionEnabled:true];
UITapGestureRecognizer *mainViewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTextViewTap:)];
UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap2:)];
[_answerTextView addGestureRecognizer:mainViewTap];
[self addGestureRecognizer:tap2];
return _answerTextView;
}
I want the UITextView to simply show the keyboard when the user taps on it self. What am I missing?
Edit: I have the same sources in another view, but everything works fine there. The only difference is, here the UITextView is created programmatically.
Edit 2: I got it worked. The _optionsStackView that the UITextView is added as a child is a UIStackView. I tried adding the _answerTextView to the parent UIView and everything works fine now. What would be the problem with the UIStackView?
Your problem very strange in your code.You can explantion why use UITapGestureRecognizer to this UITextView control.How do you think this lead to conflict?
I find your problem where in start,but I create new project to ensure.So I confirm that UITextView already has target with itself.Also you can't to add UITapGestureRecognizer.
What you're doing is almost correct, but just try changing endEditing: to [textView resignFirstResponder]:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
If that doesn't work, then it could be that one of your gestures is preventing the UITextView's own UITapGestureRecognizer from receiving the tap. Try disabling (or comment out the creation of) both of your recognizers to verify that it is the issue. If it is, then you can fix it using the UIGestureRecognizerDelegate methods.
You did not use common way to hide/close the keyboard.
Try this common way:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
return [textField resignFirstResponder];
}
This is a method in the UITextFieldDelegate, use it and remove your code:
if([text isEqualToString:#"\n"]) {
[self endEditing:YES];
return NO;
}
Edit:
#siburb You are right. My bad.
UITapGestureRecognizer maybe the root cause.
Edit:
#Semih Akbas
Repalce:
[_optionsStackView addSubview:_answerTextView];
To:
[_optionsStackView addArrangedSubview:_answerTextView];

Limit the text input boundaries on iOS

I am developing an app for my company but i am no expert on obj-C programming language. I've tried to find some answers on the internet but no success at all. The solution to the problem may be simple, but i am unable to solve it.
I want to limit the text so it fits inside the text box. What is happening right now is as i start typing and it flows on the first line forever and do not change drop to the second line when it hits the box boundaries.
otherdetails = [[UITextField alloc] initWithFrame:otherdetailsf];
otherdetails.text = otherdetailstxt;
[otherdetails.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]];
[otherdetails.layer setBorderWidth:2.0];
otherdetails.layer.cornerRadius = 5;
otherdetails.clipsToBounds = YES;
otherdetails.delegate = self;
otherdetails.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
otherdetails.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
Thats what happens when i type a lot on the text field....
How can i solve this problem?
Thanks!!
Use TextViewinstead of text field if you need to support multiple lines of text whenever the text reaches the end of a line.
From Documentation:
The UITextView class implements the behavior for a scrollable,
multiline text region. The class supports the display of text using
custom style information and also supports text editing. You typically
use a text view to display multiple lines of text, such as when
displaying the body of a large text document.
So your code should be:
otherDetails=[[UITextView alloc]initWithFrame:otherdetailsf];
otherDetails.text=#"";
[otherDetails.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]];
[otherDetails.layer setBorderWidth:2.0];
otherDetails.layer.cornerRadius = 5;
otherDetails.clipsToBounds = YES;
otherDetails.delegate = self;
// otherDetails.contentMode=UIControlContentVerticalAlignmentTop;
try this code:
in viewcontroller.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITextViewDelegate>
#property (strong,nonatomic)IBOutlet UITextView *mytextview;
#end
in viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize mytextview;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)addTextView
{
[mytextview setText:#"Lorem ipsum dolor sit er elit lamet"];
mytextview.delegate = self;
[self.view addSubview:mytextview];
mytextview.delegate = self;
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:
(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
}
return YES;}
-(void)textViewDidBeginEditing:(UITextView *)textView{
NSLog(#"Did begin editing");
}
-(void)textViewDidChange:(UITextView *)textView{
NSLog(#"Did Change");
}
-(void)textViewDidEndEditing:(UITextView *)textView{
NSLog(#"Did End editing");
}
-(BOOL)textViewShouldEndEditing:(UITextView *)textView{
[textView resignFirstResponder];
return YES;
}
#end

Intercept UITextField touch

I would like to intercept a touch on a UITextField, for instance when I first load it I give it a #selector() to load a different method instead of the delegate stuff?
This is my attempt:
descriptionText = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 25.0, infoView.frame.size.width - 20, 100.0)];
descriptionText.backgroundColor = [UIColor whiteColor];
descriptionText.textColor = [UIColor blackColor];
descriptionText.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
descriptionText.userInteractionEnabled = YES;
[descriptionText addTarget:self action:#selector(loadInfoView:) forControlEvents:UIControlEventTouchUpInside];
descriptionText.font = [UIFont fontWithName:#"Helvetica" size:15];
// show view
[infoView addSubview:descriptionText];
However when I debug the method:
- (void)loadInfoView
{
NSLog(#"load other view here");
}
Your problem is in the forControlEvents:: try UIControlEventEditingDidBegin
[descriptionText addTarget:self action:#selector(loadInfoView:) UIControlEventEditingDidBegin];
Your #selector(loadInfoView:) is also wrong if you have - (void)loadInfoView
or #selector(loadInfoView:) and - (void)loadInfoView: (id) sender
or #selector(loadInfoView) and - (void)loadInfoView
However, why you don't use the UITextFieldDelegate?
.m
#interface ViewController () <UITextFieldDelegate>
#property (strong, nonatomic) UITextField *descriptionText;
#end
Remember to:
self.descriptionText.delegate = self;
Then:
-(void) textFieldDidBeginEditing:(UITextField *)textField
{
if (textField == self.descriptionText)
{
[self loadInfoView];
}
}
Keyboard:
If you don't want to show the keyboard you need to add a [descriptionText resignFirstResponder];
I'm not sure you can get actions to be called on a text field on touch like you want.
If that doesn't work, why don't you attach a tap gesture recognizer to your text field?

Unable to hide the keyboard in iOS

I am trying to hide the keyboard in an iOS app. I've spent several hours looking for it, and I've tried pretty much everything, so I'm quite desperate.
My code follows as next:
RNViewController.h
#interface RNViewController : UIViewController <UITextFieldDelegate> {
UITextField *textField;
...
}
RNController.m
- (void)viewDidLoad {
textField.delegate = self;
textField.returnKeyType = UIReturnKeyDone;
}
- (BOOL)textFieldShouldReturn:(id)sender {
NSLog(#"Entering in textFieldShouldReturn ");
[textField resignFirstResponder];
return YES;
}
- (BOOL)textViewShouldReturn:(id)sender {
NSLog(#"Entering in textViewShouldReturn ");
[textField resignFirstResponder];
return YES;
}
- (IBAction)textFieldDoneEditing:(id)sender {
NSLog(#"Entering in textFieldDoneEditing ");
[sender resignFirstResponder];
}
- (IBAction)textViewDoneEditing:(id)sender {
NSLog(#"Entering in textViewDoneEditing ");
[sender resignFirstResponder];
}
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
EDIT: The textField is created dinamically like this:
- (void) showPreguntaTexto: (Pregunta *) pregunta {
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(CGRectGetWidth(baseView.bounds)*0.1, offset + CGRectGetWidth(baseView.bounds)*0.05, CGRectGetWidth(baseView.bounds) - CGRectGetWidth(baseView.bounds) * 0.2 , CGRectGetWidth(baseView.bounds)*0.5)];
textField.delegate = self;
[vistaAnterior addSubview:textField];
}
My views are the baseView (with elements that do not change) and vistaAnterior, that has the content (and the textField) and changes.
Trying this, it shows that entered to textFieldShouldReturn, but the keyboard does not dissapear.
Why is this happening?? Please help!!
Resign the sender of the textfield instead of your instance. UITextField *textField is not an IBOutlet (storyboard) or created in code so textField is nil (unless you created it somewhere else and didn't show the code).
- (BOOL)textViewShouldReturn:(id)sender {
NSLog(#"Entering in textViewShouldReturn ");
[sender resignFirstResponder];
return YES;
}
have you set text fields delegate in your RNViewController from stroyboard. This might be a reason for keyboard not hiding.

How to dismiss keyboard iOS programmatically when pressing return

I created a UITextField programmatically making the UITextField a property of the viewController. I need to dismiss the keyboard with the return and the touch on the screen. I was able to get the screen touch to dismiss, but pressing return is not working.
I've seen how to do it with storyboards and by allocating and initializing the UITextField object directly without creating it as a property. Possible to do?
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate>
#property (strong, atomic) UITextField *username;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor blueColor];
self.username = [[UITextField alloc] initWithFrame:CGRectMake(100, 25, 80, 20)];
self.username.placeholder = #"Enter your username";
self.username.backgroundColor = [UIColor whiteColor];
self.username.borderStyle = UITextBorderStyleRoundedRect;
if (self.username.placeholder != nil) {
self.username.clearsOnBeginEditing = NO;
}
_username.delegate = self;
[self.view addSubview:self.username];
[_username resignFirstResponder];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"touchesBegan:withEvent:");
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
#end
The simple way is to connect the delegate of UITextField to self (self.mytestField.delegate = self) and dismiss the keyboard in the method textFieldShouldReturn using [textField resignFirstResponder];
Another way to dismiss the keyboard is the following:
Objective-C
[self.view endEditing:YES];
Swift:
self.view.endEditing(true)
Put [self.view endEditing:YES]; where you would like to dismiss the keyboard (Button event, Touch event, etc.).
Add a delegate method of UITextField like this:
#interface MyController : UIViewController <UITextFieldDelegate>
And set your textField.delegate = self; then also add two delegate methods of UITextField
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return YES;
}
// It is important for you to hide the keyboard
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
simply use this in swift to dismiss keyboard:
UIApplication.sharedApplication().sendAction("resignFirstResponder", to:nil, from:nil, forEvent:nil)
Swift 3
UIApplication.shared.sendAction(#selector(UIResponder.resign‌​FirstResponder), to: nil, from: nil, for: nil)
//Hide keyBoard by touching background in view
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self view] endEditing:YES];
}
SWIFT 4:
self.view.endEditing(true)
or
Set text field's delegate to current viewcontroller and then:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
Objective-C:
[self.view endEditing:YES];
or
Set text field's delegate to current viewcontroller and then:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
In the App Delegate, you can write
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.window endEditing:YES];
}
use this way, you can don`t write too much code.
Try to get an idea about what a first responder is in iOS view hierarchy. When your textfield becomes active(or first responder) when you touch inside it (or pass it the messasge becomeFirstResponder programmatically), it presents the keyboard. So to remove your textfield from being the first responder, you should pass the message resignFirstResponder to it there.
[textField resignFirstResponder];
And to hide the keyboard on its return button, you should implement its delegate method textFieldShouldReturn: and pass the resignFirstResponder message.
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
Here's what I use in my code. It works like a charm!
In yourviewcontroller.h add:
#property (nonatomic) UITapGestureRecognizer *tapRecognizer;
Now in the .m file, add this to your ViewDidLoad function:
- (void)viewDidLoad {
[super viewDidLoad];
//Keyboard stuff
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapRecognizer];
}
Also, add this function in the .m file:
- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
[self.view endEditing:YES];
}
For a group of UITextViews inside a ViewController:
Swift 3.0
for view in view.subviews {
if view is UITextField {
view.resignFirstResponder()
}
}
Objective-C
// hide keyboard before dismiss
for (UIView *view in [self.view subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
// no need to cast
[view resignFirstResponder];
}
}
To dismiss a keyboard after the keyboard has popped up, there are 2 cases,
when the UITextField is inside a UIScrollView
when the UITextField is outside a UIScrollView
2.when the UITextField is outside a UIScrollView
override the method in your UIViewController subclass
you must also add delegate for all UITextView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
In a scroll view, Tapping outside will not fire any event, so in that case use a Tap Gesture Recognizer,
Drag and drop a UITapGesture for the scroll view and create an IBAction for it.
to create a IBAction, press ctrl+ click the UITapGesture and drag it to the .h file of viewcontroller.
Here I have named tappedEvent as my action name
- (IBAction)tappedEvent:(id)sender {
[self.view endEditing:YES]; }
the abouve given Information was derived from the following link, please refer for more information or contact me if you dont understand the abouve data.
http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/
I know this have been answered by others, but i found the another article that covered also for no background event - tableview or scrollview.
http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/
Since the tags only say iOS i will post the answer for Swift 1.2 and iOs 8.4, add these in your view controller swift class:
// MARK: - Close keyboard when touching somewhere else
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
// MARK: - Close keyboard when return pressed
func textFieldShouldReturn(textField: UITextField!) -> Bool {
textField.resignFirstResponder()
return true
}
// MARK: -
Also do not forget to add UITextFieldDelegate in the class declaration and set your text fields delegate to self (the view).
IN Swift 3
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
OR
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == yourtextfieldName
{
self.resignFirstResponder()
self.view.endEditing(true)
}
}
First you need to add textfield delegete in .h file. if not declare
(BOOL)textFieldShouldReturn:(UITextField *)textField this method not called.so first add delegate and write keyboard hide code into that method.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
try this one..
So here's what I did to make it dismiss after touching the background or return. I had to add the delegate = self in viewDidLoad and then also the delegate methods later in the .m files.
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITextFieldDelegate>
#property (strong, atomic) UITextField *username;
#end
.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor blueColor];
self.username = [[UITextField alloc] initWithFrame:CGRectMake(100, 25, 80, 20)];
self.username.placeholder = #"Enter your username";
self.username.backgroundColor = [UIColor whiteColor];
self.username.borderStyle = UITextBorderStyleRoundedRect;
if (self.username.placeholder != nil) {
self.username.clearsOnBeginEditing = NO;
}
self.username.delegate = self;
[self.username resignFirstResponder];
[self.view addSubview:self.username];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
#end
Simply use this in Objective-C to dismiss keyboard:
[[UIApplication sharedApplication].keyWindow endEditing:YES];
Add Delegate : UITextFieldDelegate
#interface ViewController : UIViewController <UITextFieldDelegate>
and then add this delegate method
// This should work perfectly
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view.subviews enumerateObjectsUsingBlock:^(UIView* obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UITextField class]]) {
[obj resignFirstResponder];
}
}];
}
when you using more then one textfield in screen
With this method you doesn't need to mention textfield every time like
[textField1 resignFirstResponder];
[textField2 resignFirstResponder];
Swift 2 :
this is what is did to do every thing !
close keyboard with Done button or Touch outSide ,Next for go to next input.
First Change TextFiled Return Key To Next in StoryBoard.
override func viewDidLoad() {
txtBillIdentifier.delegate = self
txtBillIdentifier.tag = 1
txtPayIdentifier.delegate = self
txtPayIdentifier.tag = 2
let tap = UITapGestureRecognizer(target: self, action: "onTouchGesture")
self.view.addGestureRecognizer(tap)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if(textField.returnKeyType == UIReturnKeyType.Default) {
if let next = textField.superview?.viewWithTag(textField.tag+1) as? UITextField {
next.becomeFirstResponder()
return false
}
}
textField.resignFirstResponder()
return false
}
func onTouchGesture(){
self.view.endEditing(true)
}
If you don't know current view controller or textview you can use the Responder Chain:
UIApplication.shared.sendAction(#selector(UIView.endEditing(_:)), to:nil, from:nil, for:nil)
for swift 3-4 i fixed like
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
just copy paste anywhere on the class. This solution just work if you want all UItextfield work as same, or if you have just one!

Resources