UITextField has trailing whitespace after secureTextEntry toggle - ios

I have a button that toggles between Show/Hide mode (i.e. toggles a UITextField between secureTextEntry NO and YES). The purpose of which is to allow the user to see the password they are entering.
I followed the example (with the highest number of votes) here: UITextField secureTextEntry - works going from YES to NO, but changing back to YES has no effect
However, when I set secureTextEntry to NO, any text that was written there ends up with a space at the end. This does not seem to be a problem when setting secureTextEntry to YES.
For example, if I enter the text "mypassword" while setSecureTextEntry is set to NO, and then switch it to YES, the user will see ********** (10 dots), which is correct. If I setSecureTextEntry to NO, the user will see "mypassword " (with a space at the end, or at least, the cursor moved one space to the right).
Important note: In the debugger, the string value of text appears without the trailing space, like this:
(lldb) expr self.passwordText.text
(NSString *) $0 = 0x1d8450e0 #"mypassword"
I have tried trimming whitespace (per avoid middle whitespace in UITextField), but it has had no effect.

i've just encounter this case and finally solved this problem.
works on Latest iOS SDK, iOS 8.1
First of all, there is no trailing space at all.
The dot(shown in SecureEntry) character and normal character have different width and after you toggle isSecureEntry switch, the cursor didn't refresh it's position.
so i use this workaround to solved this problem.
- (void)toggle
{
NSString *tmpString;
[self.passwordTextField setSecureTextEntry:!self.passwordTextField.isSecureTextEntry];
if (self.passwordTextField.isSecureTextEntry) {
// do stuffs
} else {
// do other stuffs
}
// Workaround to refresh cursor
tmpString = self.passwordTextField.text;
self.passwordTextField.text = #" ";
self.passwordTextField.text = tmpString;
}
Swift 3+
// Workaround to refresh cursor
let currentText: String = self.userPassword.text!
self.userPassword.text = "";
self.userPassword.text = currentText
hope it helps!

PRE-iOS-8.0 (dated solution)... In your button's action method (toggling between secureTextEntry YES and NO), simply set UITextField's text property to its current text value. Although this may seem redundant and a bit like a hack, this will redraw the cursor in the right position. Here's an example of what your button's action method should look like now...
-(void)toggleButtonPressed:(UIButton*)sender
{
// Toggle between secure and not-so-secure entry
self.toggleButton.selected = !self.toggleButton.selected;
self.textfield.secureTextEntry = !self.toggleButton.selected;
// * Redundant (but necessary) line *
[self.textfield setText:self.textfield.text];
}
POST-iOS-8.0... As of iOS 8.0, it appears that UITextField's text setter no longer redraws the cursor when called with a string equal to its current string value. Now, we need to take this a step further and actually change the text value before resetting it again. Replace the above setText: line with something like these lines.
// * Extra redundant (but necessary) lines *
NSString *currentText = self.textfield.text;
[self.textfield setText:#"Arbitrary string..."]; // Change the value
[self.textfield setText:currentText]; // Reset the value

I have a clean solution not going dirty with text property of UITextField.
Wrap them in this style.
[self.passwordTextField resignFirstResponder]; // first resign its first responder.
// change `secureTextEntry` property's value if necessary.
if (self.passwordTextField.secureTextEntry) {
self.passwordTextField.secureTextEntry = NO;
self.passwordEcryptButton.selected = YES;
}else{
self.passwordTextField.secureTextEntry = YES;
self.passwordEcryptButton.selected = NO;
}
[self.passwordTextField becomeFirstResponder]; // finally gain its first responder again.

In order to work around this bug in iOS you can simply do the following (works for any iOS version):
- (IBAction)toggleSecureTextEntry:(UIButton *)button
{
self.textField.secureTextEntry = !self.textField.secureTextEntry;
NSString *originalText = self.textField.text;
self.textField.text = nil;
self.textField.text = originalText;
}

You can fix it like this:
NSString *currentText = self.textfield.text;
self.textfield.text = #"";
self.textfield.text = currentText;

This work for me on iOS 8
if (self.passwordTextField.secureTextEntry) {
// Display password and keep selected text range
UITextRange *selectedTextRange = self.passwordTextField.selectedTextRange;
NSString *password = self.passwordTextField.text;
self.passwordTextField.secureTextEntry = NO;
self.passwordTextField.text = [#"" stringByPaddingToLength:password.length withString:#" " startingAtIndex:0]; // Done for carret redrawing
self.passwordTextField.text = password;
self.passwordTextField.selectedTextRange = selectedTextRange;
}
else {
// Hide password and keep selected text range
UITextRange *selectedTextRange = self.passwordTextField.selectedTextRange;
NSString *password = self.passwordTextField.text;
self.passwordTextField.secureTextEntry = YES;
self.passwordTextField.text = [#"" stringByPaddingToLength:password.length withString:#" " startingAtIndex:0]; // Done for carret redrawing
self.passwordTextField.text = password;
self.passwordTextField.selectedTextRange = selectedTextRange;
}

UITextPosition *beginning = [self.passwordField beginningOfDocument];
[self.passwordField setSelectedTextRange:[self.passwordField textRangeFromPosition:beginning
toPosition:beginning]];
UITextPosition *end = [self.passwordField endOfDocument];
[self.passwordField setSelectedTextRange:[self.passwordField textRangeFromPosition:end
toPosition:end]];
This is what I used for iOS 8

When we change a textfield.secureTextEntry property, the caret position is not updated. To fix this, the code below used to work before IOS 8:
pwdTextField.text = pwdTextField.text
Now it doesn't. It seems IOS 8 detects the new value equals old value and does nothing. So to make it work again we have to actually change the value. Here is the swift version that works for me.
let str = pwdTextField.text
pwdTextField.text = str + " "
pwdTextField.text = str

This is another possibility to solve this issue, where self.passwordText is the UITextField:
if (self.passwordText.isFirstResponder) {
[self.passwordText resignFirstResponder];
[self.passwordText becomeFirstResponder];
}

It appears that the second solution in the referenced link, when implemented, has the desired behavior of not adding an extra space:
https://stackoverflow.com/a/8495888/738190

This Works in my case
BOOL wasFirstResponder = [self.passwordTextField isFirstResponder];
if([self.passwordTextField isSecureTextEntry])
{
//This three lines are key
self.passwordTextField.delegate = nil;
[self.passwordTextField resignFirstResponder];
self.passwordTextField.delegate = self;
}
[self.passwordTextField setSecureTextEntry: !self.passwordTextField.isSecureTextEntry];
if(wasFirstResponder)
[self.passwordTextField becomeFirstResponder];

Swift UITextField extension:
extension UITextField {
func toggleSecureEntry() {
let wasFirstResponder = isFirstResponder
if wasFirstResponder { resignFirstResponder() }
isSecureTextEntry.toggle()
if wasFirstResponder { becomeFirstResponder() }
}
}
Setting textField.text solution also works in some situations but not for my need (Custom font with two text fields. Caused font changes and glitches on runtime.) Adding here too.
func toggleSecureEntry() {
isSecureTextEntry.toggle()
let originalText = text
text = nil
text = originalText
}

To get the cursor to reposition correctly, setting the font attributes seemed to do the trick for me.
// Hack to update cursor position
self.passwordTf.defaultTextAttributes = #{NSFontAttributeName: textFieldFont, NSForegroundColorAttributeName: textFieldColor};
// Change secure entry
self.passwordTf.secureTextEntry = !self.passwordTf.secureTextEntry;
Tested on iOS8, iOS9.
Hope it helps!

Everytime the text is set in the UITextField, the cursor postition is updated
So I used this code
partial void btnShowPassword_ToutchUpInside (UIButton sender)
{
if (TxtPassword.SecureTextEntry == true) {
TxtPassword.SecureTextEntry = false;
TxtPassword.Text = TxtPassword.Text;
} else {
TxtPassword.SecureTextEntry = true;
}
}

Here is the solution:
- (void)showHidePassword:(UIButton *)sender {
EDSignUpCell *cell = [self.signUpTblView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]];
if(!TRIM_SPACE(cell.cellTextField.text).length) {return;}
[cell.showHidePasswordBtn setSelected:!cell.showHidePasswordBtn.isSelected];
cell.cellTextField.secureTextEntry = cell.showHidePasswordBtn.isSelected;
[cell.cellTextField setText:cell.cellTextField.text];
[cell.cellTextField becomeFirstResponder];
}

I'm using this, Works fine.
[self.yourTextField becomeFirstResponder];

Swift 4
Bug is on radar, there is explanation of workaround also: http://www.openradar.me/38465011
Here is cut of temporary workaround how to natively update caret (cursor) position.
// update caret position
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
let (beginning, end) = (self.beginningOfDocument, self.endOfDocument)
self.selectedTextRange = self.textRange(from: beginning, to: end)
self.selectedTextRange = self.textRange(from: end, to: end)
}

I had a similar issue and realized it was because I was updating the text before setting the secureTextEntry property. It makes sense that the textField would draw out the caret at the location it'd be at if it were using secureTextEntry.
I did not read the entire problem nor did I visit the solution linked by OP, but in case someone else has the same issue as me:
Try updating your text after setting the secureTextEntry property.

Related

Why does the font on iOS textfields changes upon altering secureTextEntry programatically? [duplicate]

I’m using a custom font in a UITextField, which has secureTextEntry turned on. When I’m typing in the cell, I see the bullets in my chosen font, but when the field loses focus, those bullets revert to the system standard font. If I tap the field again, they change back to my font, and so on.
Is there a way I can ensure that they continue to display the custom font’s bullets, even when the field is out of focus?
A subclass that works this issue around. Create an arbitrary UITextField, then set the secure property to YES (via KVC in IB).
Actually it implements a comment suggested by lukech. When textfield ends editing, it switches to an arbitrary textfield, then set a bulk of dots into, and some hack in text accessor to always get the actual text the field holds.
#interface SecureTextFieldWithCustomFont : UITextField
#property (nonatomic) BOOL secure;
#property (nonatomic, strong) NSString *actualText;
#end
#implementation SecureTextFieldWithCustomFont
-(void)awakeFromNib
{
[super awakeFromNib];
if (self.secureTextEntry)
{
// Listen for changes.
[self addTarget:self action:#selector(editingDidBegin) forControlEvents:UIControlEventEditingDidBegin];
[self addTarget:self action:#selector(editingDidChange) forControlEvents:UIControlEventEditingChanged];
[self addTarget:self action:#selector(editingDidFinish) forControlEvents:UIControlEventEditingDidEnd];
}
}
-(NSString*)text
{
if (self.editing || self.secure == NO)
{ return [super text]; }
else
{ return self.actualText; }
}
-(void)editingDidBegin
{
self.secureTextEntry = YES;
self.text = self.actualText;
}
-(void)editingDidChange
{ self.actualText = self.text; }
-(void)editingDidFinish
{
self.secureTextEntry = NO;
self.actualText = self.text;
self.text = [self dotPlaceholder];
}
-(NSString*)dotPlaceholder
{
int index = 0;
NSMutableString *dots = #"".mutableCopy;
while (index < self.text.length)
{ [dots appendString:#"•"]; index++; }
return dots;
}
#end
May be augmented to work with non NIB instantiations, handling default values, etc, but you probably get the idea.
For those having trouble with losing custom fonts when toggling secureTextEntry, I found a work-around (I'm using the iOS 8.4 SDK). I was trying to make a toggle for showing/hiding a password in a UITextField. Every time I'd toggle secureTextEntry = NO my custom font got borked, and only the last character showed the correct font. Something funky is definitely going on with this, but here's my solution:
-(void)showPassword {
[self.textField resignFirstResponder];
self.textField.secureTextEntry = NO;
}
First responder needs to be resigned for some reason. You don't seem to need to resign the first responder when setting secureTextEntry to YES, only when setting to NO.
The actual problem appears to be that the editing view (UITextField does not draw its own text while editing) uses bullets (U+2022) to draw redacted characters, while UITextField uses black circles (U+25CF). I suppose that in the default fonts, these characters look the same.
Here's an alternate workaround for anyone interested, which uses a custom text field subclass, but doesn't require juggling the text property or other special configuration. IMO, this keeps things relatively clean.
#interface MyTextField : UITextField
#end
#implementation MyTextField
- (void)drawTextInRect:(CGRect)rect
{
if (self.isSecureTextEntry)
{
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = self.textAlignment;
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setValue:self.font forKey:NSFontAttributeName];
[attributes setValue:self.textColor forKey:NSForegroundColorAttributeName];
[attributes setValue:paragraphStyle forKey:NSParagraphStyleAttributeName];
CGSize textSize = [self.text sizeWithAttributes:attributes];
rect = CGRectInset(rect, 0, (CGRectGetHeight(rect) - textSize.height) * 0.5);
rect.origin.y = floorf(rect.origin.y);
NSMutableString *redactedText = [NSMutableString new];
while (redactedText.length < self.text.length)
{
[redactedText appendString:#"\u2022"];
}
[redactedText drawInRect:rect withAttributes:attributes];
}
else
{
[super drawTextInRect:rect];
}
}
#end
While this is an iOS bug (and new in iOS 7, I should add), I do have another way to work around it that one might find acceptable. The functionality is still slightly degraded but not by much.
Basically, the idea is to set the font to the default font family/style whenever the field has something entered in it; but when nothing is entered, set it to your custom font. (The font size can be left alone, as it's the family/style, not the size, that is buggy.) Trap every change of the field's value and set the font accordingly at that time. Then the faint "hint" text when nothing is entered has the font that you want (custom); but when anything is entered (whether you are editing or not) will use default (Helvetica). Since bullets are bullets, this should look fine.
The one downside is that the characters, as you type before being replaced by bullets, will use default font (Helvetica). That's only for a split second per character though. If that is acceptable, then this solution works.
I found a trick for this issue.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if ([textField tag]== TAG_PASS || [textField tag]== TAG_CPASS)
{
// To fix password dot size
if ([[textField text] isEqualToString:#"" ])
{
[textField setText:#" "];
[textField resignFirstResponder];
[textField becomeFirstResponder];
[textField setText:#""];
}
}
}
[passWordTextField resignFirstResponder];
passWordTextField.secureTextEntry = !passWordTextField.secureTextEntry;
[passWordTextField becomeFirstResponder];
This is the fastest way to solve this bug!
iOS is acting a bit strange when it comes to custom fonts. Try removing "Adjust to Fit" for that textfield. If that doesn't work, I'm guessing that what bothering you is the size increase of the font.
A simple solution for that would be:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if(textField.secureTextEntry)
{
[textField setFont:[UIFont fontWithName:#"Helvetica-Bold" size:10.0]];
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
if(textField.secureTextEntry)
{
[textField setFont:[UIFont fontWithName:#"Helvetica-Bold" size:10.0]];
}
}
You'll need to play with the size a bit in order for it to look like there is no size change when loosing focus on the UITextField.
If you have a major spacing problem between characters like in the edited question, the simplest (and a bit ugly) solution would be to create a Bullet image that matches the above size & spacing and matches the amount of characters entered by the user that will appear when the user leaves the UITextField.
A secureTextEntry text field can be avoided altogether:
NSString *pin = #"";
BOOL pasting = FALSE;
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(!pasting) {
pin = [pin stringByReplacingCharactersInRange:range withString:string];
// Bail out when deleting a character
if([string length] == 0) {
return YES;
}
pasting = TRUE;
[textField paste:#"●"];
return NO;
} else {
pasting = FALSE;
return YES;
}
}
I recommend to resignFirstResponder before you change scureTextEntry and then becomeFirstResponder again as it is posted here: https://stackoverflow.com/a/34777286/1151916
Swift 5 and iOS 14 is around but isSecureTextEntry set to true for custom font still displays the wrong size bullets, although the actual leading letter is of the correct size.
None of the solutions from stack overflow has worked for me except a hacky workaround of setting the font to the system font when password is in secure mode.
if textField.isSecureTextEntry {
self.textField.font = UIFont.systemFont(ofSize: 17)
} else {
self.textField.font = UIFont(name: "Roboto-Regular", size: 17)
}

iOS - appending string before and after the word

I want to add a string in the highlighted area in the textview, I mean by the highlighted area, where the blue line is located.
So once the user click on the button it adds a string where the "blue line" is located
I used stringByAppendingString but it adds the string after the word exists only
NSRange range = myTextView.selectedRange;
NSString * firstHalfString = [myTextView.text substringToIndex:range.location];
NSString * secondHalfString = [myTextView.text substringFromIndex: range.location];
myTextView.scrollEnabled = NO; // turn off scrolling
NSString * insertingString = [NSString stringWithFormat:#"your string value here"];
myTextView.text = [NSString stringWithFormat: #"%#%#%#",
firstHalfString,
insertingString,
secondHalfString];
range.location += [insertingString length];
myTextView.selectedRange = range;
myTextView.scrollEnabled = YES;
You need to use the selectedRange to find out where the text cursor is. Then use replaceCharactersInRange:withString: or insertString:atIndex: to insert the new text into the original text. Then update the text into the view.
Even though its not clear what you are trying to achieve, it seems that you want the user to start editing the textfield from the position where text starts. In that case , you can refer following:
Hint 1
Set your view controller (or some other appropriate object) as the text field's delegate and implement the textFieldDidBeginEditing: method like this:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
UITextPosition *beginning = [textField beginningOfDocument];
[textField setSelectedTextRange:[textField textRangeFromPosition:beginning
toPosition:beginning]];
}
Note that setSelectedTextRange: is a protocol method of UITextInput (which UITextField implements), so you won't find it directly in the UITextField documentation.
Hint 2
self.selectedTextRange = [self textRangeFromPosition:newPos toPosition:newPos];
Hint 3
finding-the-cursor-position-in-a-uitextfield/

How to ignore placeholder text in iOS6 UITextField

I have a data entry app which I have developed primarily with iOS7 in focus but it will support ios 6. I noticed that when I am trying to check if a UITextField is empty when I try to validate a form in iOS6 it will tell me that it is not empty if there is a placeholder text there. In iOS 7 I don't have this problem.
Does anyone have any efficient solution for this except for matching every UITextField's content with its placeholdet text for all the UITextFields in the whole app?
EDIT:
If the validation is the issue, here is my validation code. Very simply I iterate through an array with the mandatory UITextFields and check if there is any input in them.
-(void)checkIfComplete{
BOOL complete = YES;
for(int i = 0; i < self.mandatoryFields.count; i++){
UITextField *tempTextField = self.mandatoryFields[i];
if([tempTextField.text isEqual: #""]){
complete = NO;
}
}
if(complete){
self.btnSave.enabled = YES;
}else{
self.btnSave.enabled = NO;
}
}
EDIT 2:
Okey this is very weird. When I load the ViewController with the UITextFields the validation is wrong (it says the form is complete even though it is not). But if I enter a UITextField, write something and then delete what I just wrote the validation is correct (it says the form is incomplete when it is). I am setting my placeholders from the Storyboard if that makes any difference.
Thank you
Try this
-(void)checkIfComplete{
BOOL complete = YES;
for(int i = 0; i < self.mandatoryFields.count; i++){
UITextField *tempTextField = self.mandatoryFields[i];
if(tempTextField.text.length == 0){
complete = NO;
break;
}
}
self.btnSave.enabled = complete;
}

UITextField secureTextEntry bullets with a custom font?

I’m using a custom font in a UITextField, which has secureTextEntry turned on. When I’m typing in the cell, I see the bullets in my chosen font, but when the field loses focus, those bullets revert to the system standard font. If I tap the field again, they change back to my font, and so on.
Is there a way I can ensure that they continue to display the custom font’s bullets, even when the field is out of focus?
A subclass that works this issue around. Create an arbitrary UITextField, then set the secure property to YES (via KVC in IB).
Actually it implements a comment suggested by lukech. When textfield ends editing, it switches to an arbitrary textfield, then set a bulk of dots into, and some hack in text accessor to always get the actual text the field holds.
#interface SecureTextFieldWithCustomFont : UITextField
#property (nonatomic) BOOL secure;
#property (nonatomic, strong) NSString *actualText;
#end
#implementation SecureTextFieldWithCustomFont
-(void)awakeFromNib
{
[super awakeFromNib];
if (self.secureTextEntry)
{
// Listen for changes.
[self addTarget:self action:#selector(editingDidBegin) forControlEvents:UIControlEventEditingDidBegin];
[self addTarget:self action:#selector(editingDidChange) forControlEvents:UIControlEventEditingChanged];
[self addTarget:self action:#selector(editingDidFinish) forControlEvents:UIControlEventEditingDidEnd];
}
}
-(NSString*)text
{
if (self.editing || self.secure == NO)
{ return [super text]; }
else
{ return self.actualText; }
}
-(void)editingDidBegin
{
self.secureTextEntry = YES;
self.text = self.actualText;
}
-(void)editingDidChange
{ self.actualText = self.text; }
-(void)editingDidFinish
{
self.secureTextEntry = NO;
self.actualText = self.text;
self.text = [self dotPlaceholder];
}
-(NSString*)dotPlaceholder
{
int index = 0;
NSMutableString *dots = #"".mutableCopy;
while (index < self.text.length)
{ [dots appendString:#"•"]; index++; }
return dots;
}
#end
May be augmented to work with non NIB instantiations, handling default values, etc, but you probably get the idea.
For those having trouble with losing custom fonts when toggling secureTextEntry, I found a work-around (I'm using the iOS 8.4 SDK). I was trying to make a toggle for showing/hiding a password in a UITextField. Every time I'd toggle secureTextEntry = NO my custom font got borked, and only the last character showed the correct font. Something funky is definitely going on with this, but here's my solution:
-(void)showPassword {
[self.textField resignFirstResponder];
self.textField.secureTextEntry = NO;
}
First responder needs to be resigned for some reason. You don't seem to need to resign the first responder when setting secureTextEntry to YES, only when setting to NO.
The actual problem appears to be that the editing view (UITextField does not draw its own text while editing) uses bullets (U+2022) to draw redacted characters, while UITextField uses black circles (U+25CF). I suppose that in the default fonts, these characters look the same.
Here's an alternate workaround for anyone interested, which uses a custom text field subclass, but doesn't require juggling the text property or other special configuration. IMO, this keeps things relatively clean.
#interface MyTextField : UITextField
#end
#implementation MyTextField
- (void)drawTextInRect:(CGRect)rect
{
if (self.isSecureTextEntry)
{
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = self.textAlignment;
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setValue:self.font forKey:NSFontAttributeName];
[attributes setValue:self.textColor forKey:NSForegroundColorAttributeName];
[attributes setValue:paragraphStyle forKey:NSParagraphStyleAttributeName];
CGSize textSize = [self.text sizeWithAttributes:attributes];
rect = CGRectInset(rect, 0, (CGRectGetHeight(rect) - textSize.height) * 0.5);
rect.origin.y = floorf(rect.origin.y);
NSMutableString *redactedText = [NSMutableString new];
while (redactedText.length < self.text.length)
{
[redactedText appendString:#"\u2022"];
}
[redactedText drawInRect:rect withAttributes:attributes];
}
else
{
[super drawTextInRect:rect];
}
}
#end
While this is an iOS bug (and new in iOS 7, I should add), I do have another way to work around it that one might find acceptable. The functionality is still slightly degraded but not by much.
Basically, the idea is to set the font to the default font family/style whenever the field has something entered in it; but when nothing is entered, set it to your custom font. (The font size can be left alone, as it's the family/style, not the size, that is buggy.) Trap every change of the field's value and set the font accordingly at that time. Then the faint "hint" text when nothing is entered has the font that you want (custom); but when anything is entered (whether you are editing or not) will use default (Helvetica). Since bullets are bullets, this should look fine.
The one downside is that the characters, as you type before being replaced by bullets, will use default font (Helvetica). That's only for a split second per character though. If that is acceptable, then this solution works.
I found a trick for this issue.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if ([textField tag]== TAG_PASS || [textField tag]== TAG_CPASS)
{
// To fix password dot size
if ([[textField text] isEqualToString:#"" ])
{
[textField setText:#" "];
[textField resignFirstResponder];
[textField becomeFirstResponder];
[textField setText:#""];
}
}
}
[passWordTextField resignFirstResponder];
passWordTextField.secureTextEntry = !passWordTextField.secureTextEntry;
[passWordTextField becomeFirstResponder];
This is the fastest way to solve this bug!
iOS is acting a bit strange when it comes to custom fonts. Try removing "Adjust to Fit" for that textfield. If that doesn't work, I'm guessing that what bothering you is the size increase of the font.
A simple solution for that would be:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if(textField.secureTextEntry)
{
[textField setFont:[UIFont fontWithName:#"Helvetica-Bold" size:10.0]];
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
if(textField.secureTextEntry)
{
[textField setFont:[UIFont fontWithName:#"Helvetica-Bold" size:10.0]];
}
}
You'll need to play with the size a bit in order for it to look like there is no size change when loosing focus on the UITextField.
If you have a major spacing problem between characters like in the edited question, the simplest (and a bit ugly) solution would be to create a Bullet image that matches the above size & spacing and matches the amount of characters entered by the user that will appear when the user leaves the UITextField.
A secureTextEntry text field can be avoided altogether:
NSString *pin = #"";
BOOL pasting = FALSE;
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(!pasting) {
pin = [pin stringByReplacingCharactersInRange:range withString:string];
// Bail out when deleting a character
if([string length] == 0) {
return YES;
}
pasting = TRUE;
[textField paste:#"●"];
return NO;
} else {
pasting = FALSE;
return YES;
}
}
I recommend to resignFirstResponder before you change scureTextEntry and then becomeFirstResponder again as it is posted here: https://stackoverflow.com/a/34777286/1151916
Swift 5 and iOS 14 is around but isSecureTextEntry set to true for custom font still displays the wrong size bullets, although the actual leading letter is of the correct size.
None of the solutions from stack overflow has worked for me except a hacky workaround of setting the font to the system font when password is in secure mode.
if textField.isSecureTextEntry {
self.textField.font = UIFont.systemFont(ofSize: 17)
} else {
self.textField.font = UIFont(name: "Roboto-Regular", size: 17)
}

textview - put cursor at end of text when start editing

I am editing text in a UITextView. When the field opens for editing I need the cursor to be positioned after the final character of the existing text. The behavior I see is that the cursor is positioned more or less under the point where I touch the UITextView to start editing -- perhaps at the end of the word I touch on. I have tried setting the textview.selectedRange in both textViewDidBeginEditing: and textViewShouldBeginEditing: but that had no effect at all. I tried selecting ranges of the existing text, like {1,2} and that didn't do anything either. It seems like the selectedRange is more-or-less a read-only value?
- (void) textViewDidBeginEditing:(UITextView *)textView {
// Position the insertion cursor at the end of any existing text
NSRange insertionPoint = NSMakeRange([textView.text length], 0);
textView.selectedRange = insertionPoint;
}
How do I get the cursor to the end of the text?
The post referred to by the comment by artud2000 contains a working answer. To summarize here, add:
EDIT: The original answer was not sufficient. I've added toggling the editable property which seems to be sufficient. The problem is that the tap gesture only goes to the handler a single time (at most) and subsequent taps on the UITextField start editing directly. If it isn't editable then the UITextView's gesture recognizers are not active and the one I placed will work. This may well not be a good solution but it does seem to work.
- (void)viewDidLoad {
...
tapDescription = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tapDescription:)];
[self.descriptionTextView addGestureRecognizer:tapDescription];
self.descriptionTextView.editable = NO; // if not set in storyboard
}
- (void) tapDescription:(UIGestureRecognizer *)gr {
self.descriptionTextView.editable = YES;
[self.descriptionTextView becomeFirstResponder];
}
- (void) textViewDidEndEditing:(UITextView *)textView {
//whatever else you need to do
textView.editable = NO;
}
The default position of the cursor seems to be after any existing text which solved my problem, but if you want to you can select the text in textViewDidBeginEditing: by setting the selectedRange -- for instance:
- (void) textViewDidBeginEditing:(UITextView *)textView {
// Example: to select the second and third characters when editing starts...
NSRange insertionPoint = NSMakeRange(1, 2);
textView.selectedRange = insertionPoint;
}
Thanks for the answer Charlie Price. I used it to solve my similar problem on a UITextView. Here's the answer in Swift in case anyone needs it:
...
let tapDescription = UITapGestureRecognizer(target: self, action: #selector(MyViewController.tapDescription(_:)))
self.descriptionTextView.addGestureRecognizer(tapDescription)
self.descriptionTextView.editable = false
...
func tapDescription(gr: UIGestureRecognizer) {
self.descriptionTextView.editable = true
self.descriptionTextView.becomeFirstResponder()
}
func textViewDidEndEditing(textView: UITextView) {
self.descriptionTextView.editable = false
}

Resources