How to unclear UITextField secure text entry in Swift? - ios

When I use default Security text Entry in UITextField in Swift Language after type type text once UITextField.
Once loss focus from UITextField after try to edit Secure text then UITextField is first reset and after it start put new text in UITextField.
How to edit old Secure Text without Storing data into Any Kind of String object

I'd suggest to create a custom UITextField class and override become​First​Responder() method do add your desired functionality:
You can override this method in your custom responders to update your
object's state or perform some action such as highlighting the
selection. If you override this method, you must call super at some
point in your implementation.
The custom Class should be similar to:
class CustomSecureTextField: UITextField {
override func becomeFirstResponder() -> Bool {
super.becomeFirstResponder()
if !isSecureTextEntry { return true }
if let currentText = text { insertText(currentText) }
return true
}
}
The logic of the implementation of becomeFirstResponder as follows:
By default, the secured-entry text field clears the inserted text when it is become first responder text, so what's happening in CustomSecureTextField that if the text field is secured-entry, it will re-insert the current inserted text -after clearing it-, but you have to make sure that the text field input is secured (that's the purpose of adding if !isSecureTextEntry { return true }) or the text will be duplicated (re-inserted) each time the text field becomes first responder.
Output:
Note that both of text fields are types of CustomSecureTextField:

This answer helped me to figure out this problem.
textField.isSecureTextEntry = true
following property not gonna work if you make testField isSecureTextEntrysecure property makes true .
textField.clearsOnBeginEditing = false

There is an issue with the #Ahmd F solution when you simply tap on the field it will automatically add the text to the field I have resolved that in the below code thanks
override open func becomeFirstResponder() -> Bool {
super.becomeFirstResponder()
if !isSecureTextEntry { return true}
if let currrentText = text {
self.text = ""
insertText(currrentText)
}
return true
}

Related

The caret disappears or won't show up in UITextField

I'm having trouble with the caret of UITextfields.
Whenever I tap on the textfield the caret doesn't show, but otherwise the textfield is working properly. The problem is similar to the problem described here (already tried the solution written there as well).
I noticed that whenever I load a viewcontroller and tap on a textfield (or programatically make it the first responder) it does show a caret, but as soon as I tap another textfield or make a textfield resign its first responder status no textfield will show its caret anymore (unless I go back and reload the viewcontroller again).
Got no clue as of why this is happening. I am using a custom font throughout the app. But I'm not sure if that's what making the caret disappear, as I've used custom fonts before with no problem whatsoever.
EDIT:
I think I've at least found why the problem occurs. It is related to me overriding the becomeFirstResponder and resignFirstResponder.
My code looks like:
extension UITextField {
open override func becomeFirstResponder() -> Bool {
let willBecomeResponder = super.becomeFirstResponder()
if willBecomeResponder {
backgroundColor = .red
layer.borderColor = .blue
}
return willBecomeResponder
}
open override func resignFirstResponder() -> Bool {
let willResignResponder = super.resignFirstResponder()
if willResignResponder {
backgroundColor = .blue
layer.borderColor = .red
}
return willResignResponder
}
}
Overriding those methods in the extension makes the caret disappear.
I'm thinking this most likely happens because UITextField itself does some...'caret-management' in it's own implementation of those methods.
More so because even return super.becomeFirstResponder() and no custom code in the overridden method makes the caret disappear.
My question therefore is; how can one solve this problem without making a custom UITextField subclass?
Calling super obviously just calls the UIResponder's implementation, but the docs specifically mention:
becomeFirstResponder()
You can override this method in your custom responders to update your object's state or perform some action such as highlighting the selection. If you override this method, you must call super at some point in your implementation.
So I need to call super I guess.
Alright I solved my problem by overriding isFirstResponder and altering the textfield based on the super.isFirstResponder there.
Looks like:
open override var isFirstResponder: Bool {
get {
let responder = super.isFirstResponder
backgroundColor = (responder) ? .red : .blue
layer.borderColor = (responder) ? .blue : .red
return responder
}
}
I did noticed a lot of calls being sent to isFirstResponder, so maybe this isn't the most efficient way (if altering the textfield is a heavy op).

Swift3: best way to validate the text entered by the user in a UITextField

Evening, in my app I have several UITextfield. Each one has to confirm to different limitations.
For example, I have a date Field, zipCode Field, SSN Field etc.
From the Apple Documentation I found:
Assign a delegate object to handle important tasks, such as:
Determining whether the user should be allowed to edit the text field’s contents.
Validating the text entered by the user.
Responding to taps in the keyboard’s return button.
Forwarding the user-entered text to other parts of your app.
Store a reference to the text field in one of your controller objects.
So I'm pretty sure I have to use delegates and func textFieldDidEndEditing(_:).
The only way that came to my mind is to use a switch statement inside the func textFieldDidEndEditing(_:) to confirm the delegate to the difference limitation.
Is there a better, safer and faster pattern to face this problem?
You can set unique tag to your every text field and can compare in textFieldDidEndEditing or you can take IBOutlet of every textField and can compare it in textFieldDidEndEditing like,
func textFieldDidEndEditing(textField: UITextField) {
// By tag
if textField.tag == 100 {
}
// OR
//by outlet
if textField == self.myTextField {
}
}
You are right, you will have to check the textfield, either you can check tags assigned for different text fields using switch statement like you said,
or you can compare textfields itself,
if textfield1,textfield2 are outlets to two text fields, you can compare as following,
func textFieldDidEndEditing(textField: UITextField)
{
if textField == textfield1
{
}
else if textField == textfield2
{
}
}
you can create enum for validation
enum Type {
case zipcode
case number
}
then you can create a method for validation like this :
func isValidate(text: String, type: Type) -> Bool {
switch type {
case .zipcode:
...
}
}
this method can be in Util class. this is best practice. because your logic is encapsulate from out .
If you need more control over the text which is committed to the text field or if you want to provide feedback while the text field is being edited, you should implement a different delegate instead:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Build and check the new text value. Accept or reject the change.
}
In the delegate, you can build the new text value. Validate it, apply constraints, decide on which feedback the user should receive ("Your password must be at least eight characters long", "This is not a valid IBAN"), accept or reject the change (i.e. return false).
Keep in mind, that the delegate is not called if you assign the text property manually. Moreover, this delegate is called when text is pasted into or deleted from the text field, which can make matters much more complicated depending on what you do.

secureTextEntry doesn't hide the text of my UITextView

I'm trying to hide the text of a UITextView, used as a password entry, using dots instead of the actual text. This text view is called TV_Password.
When its empty, the text should not be hidden and should be replaced by the string "Password"
I found on the net that the solution would be to change the following property to true.
self.TV_Password.secureTextEntry = true
Unfortunately, this still doesn't hide my text.
I moved the modifications to textViewShouldBeginEditing instead of textViewDidBeginEditing, as advised to people having this kind of issue, but it still doesn't work.
I haves various breakpoints telling me the instruction IS really done, but nothing happens..
Any idea .?
//MARK: TextViews editing
func textViewShouldBeginEditing(textView: UITextView) -> Bool {
if (textView == self.TV_Password){
if (self.TV_Password.text == "Password"){
//empty text
self.TV_Password.text = ""
//enable secured text
self.TV_Password.secureTextEntry = true
}
}
return true
}
func textViewDidEndEditing(textView: UITextView) {
if (textView == self.TV_Password) {
//if password empty
if (self.TV_Password.text == ""){
//disable secured text
self.TV_Password.secureTextEntry = false
//fill with the word "Password"
self.TV_Password.text = "Password"
}
}
}
ANSWER :
UITextView doesn't have a secure entry mode, use a UITextField instead.
Thanks a lot!

Why call method to resignFirstResponder from textFieldShouldBeginEditing?

I am trying to understand delegate methods in general, and specifically how to dismiss a UIDatePicker that popovers from a text field.
According to the documentation, textFeildShouldBeginEditing returns true 'if an editing session should be initiated; otherwise, false to disallow editing.'
Why would I then tell the app to resignFirstResponder, which is meant to hide the keyboard / date picker (as in several examples on stackoverflow and noobie tutorials)?
What I don't understand is: if it should begin editing, why then hide the input devise? Obviously, I am misunderstanding one or both concepts.
func resign() {
dobTextField.resignFirstResponder()
nameTextField.resignFirstResponder()
println("resign gets printed, but the date picker is still visible!?!")
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if (textField === dobTextField) {
resign() // but should begin editing, oder?!?
}
In the examples you cite, the textField is being used to display a date. When the user selects this field, the app designers want the UIDatePicker to be displayed instead of the keyboard. Hence they call resignFirstResponder to hide the keyboard. At the same time, they display the date picker.
ResignFirstResponder will not hide the date picker, so the "input device" (for this field) will still be available.
Also, note that in one case the developer has used textFieldShouldBeginEditing, and returns false because they are providing the date picker. In the other case the developer uses textFieldDidBeginEditing (which has no return value).
you should resign only the textfield not affected:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == dobTextField {
nameTextField.resignFirstResponder()
} else if textField == nameTextField {
dobTextField.resignFirstResponder()
}
return true
}
this way you are resiging first responder only on the textfields that should not currently be edited. this helps if for some reason you accidentally have 2 textfields (or more) assigned first responder causing conflicts with multiple keyboards/datepickers and such.

iPhone/iPad: How to make UITextField readonly (but not disabled)?

I understand this question has been asked before, but I'm not satisfied with the answers, i.e. by making it disabled. There is a fundamental difference: Disabled view doesn't fire events, but for a read-only view, it should still fire event like (e.g. TouchUpInside), and I need it. Only thing I don't want is the keyboard input.
The reason is that I have several input fields, some can useUITextField directly, others are not. I want to have them look similar. So, I'd like to use UITextField to display all of them. Some of them need to be read-only so that I can use touch up event for alternative input.
Or there might be a completely different way to do it?
EDIT: This is for my MonoTouch project. I have very limited knowledge of Objective-c.
Say you have 2 text field instance variables connected to text fields you created in the Interface Builder. Lets call them myReadOnlyTextField and myEditableTextField. Make sure you connect the delegate property of each text field in the Interface Builder to the view controller ("File's Owner")[1]. Now, in the view controller #implementation (.m file), use the method textFieldShouldBeginEditing: and put in some logic to determine which text field you want to allow editing and which to not allow editing; something like this:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
BOOL editable;
if (textField == myReadOnlyTextField) {
editable = NO;
} else if (textField == myEditableTextField) {
editable = YES;
} else {
// editable = YES/NO/Other Logic
}
return editable;
}
From the UITextFieldDelegate Documentation:
textFieldShouldBeginEditing:
Asks the delegate if editing should begin
in the specified text field.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
Parameters
textField - The text field for which editing is about to
begin.
Return Value
YES if an editing session should be initiated;
otherwise, NO to disallow editing.
Discussion
When the user performs an action that would normally
initiate an editing session, the text field calls this method first to
see if editing should actually proceed. In most circumstances, you
would simply return YES from this method to allow editing to proceed.
Implementation of this method by the delegate is optional. If it is
not present, editing proceeds as if this method had returned YES.
UITextField Documentation is a good read also.
[1] You can do this programmatically as well. Here is an example:
- (void)viewDidLoad {
[super viewDidLoad];
// .....
myReadOnlyTextField.delegate = self;
myEditableTextField.delegate = self;
}
Despite the fact you need no keyboard, textField:shouldChangeCharactersInRange:replacementString: is very useful. It prevents text field from editing but still leaves it selectable in contrast to textFieldShouldBeginEditing:.
In monotouch:
var txt = new UITextField();
txt.ShouldChangeCharacters += (field, range, replacementString) => false;
You can have two options:
a) to use ShouldBeginEditing with return false, but you can't use PickerView as InputView in your text field.
b) to use ShouldChangeCharacters that will prevent the editing but will allow to use InputView with PickerView.
Objective C:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO;
}
Swift :
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
because you are working in MonoTouch you could use the following line of code:
myReadOnlyButton.ShouldBeginEditing = t =>
{
//event code
return false;
};
I personally use borderStyle = .none + userInteractionEnabled = false to make it look like a regular label.

Resources