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

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.

Related

How to unclear UITextField secure text entry in Swift?

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
}

Disable editing of a text field

I want to start by saying this is my first project and I am trying hard to find answers myself before posting here. I thought I had found the code to accomplish this. I have no errors but when I run, the field is still editable. So, how can I disable editing of my field when the rule I have set is true?
if sport.count == 1 {
enterSport.text = sport[0] as String //need to convert to a string
enterSport.editing; false //do not allow editing
} else {
//do nothing
}
I have defined the array previously so the if statement is true. Thank you for you assistance.
enterSport.userInteractionEnabled = false instead of editing.
editing is a read-only property to indicate if the field is currently being edited or not.
Swift 5:
enterSport.isUserInteractionEnabled = false
To summarize the answers and comments above:
editing is a readonly property. You can't set it.
If it's a UITextView, it has an editable property which you can set to false.
If it's a UITextField, you need to use the enabled property or the userInteractionEnabled property. Either of those will prevent editing. As
With Swift 3 Apple changed the property userInteractionEnabled to isUserInteractionEnabled.
The code looks like this:
textfield.isUserInteractionEnabled = true
There is one more way of avoiding keyboard appearing
You can set an UITapGestureRecognizer like this:
let tap = UITapGestureRecognizer(target: self, action: #selector(self.textFieldEditing))
self.enterSport.addGestureRecognizer(tap)
and
#objc func textFieldEditing() {
self.enterSport.resignFirstResponder()
}

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.

ios - I need to get the referencing outlet, or some other identifier from the sender (UITextView)

Warning: I am new to ios development but not coding in general.
I am trying to do some validation on a UITextView, several actually. All have slightly different requirements for length. I have created a custom delegate to handle this but I am running into an issue with figuring out how to make it unique to the textview sending it.
I have several fields in several different nibs that will make use of this delegate. Most of the nibs will have 3 textviews labeled something like: summary, detail and special instructions. each of these has a different max length 50, 100, 130 respectively.
TL:DR; How can I get a unique id for each sender so I can do a switch on them?
EDIT: I also would like to update a label, hidden until needed, to count down the available chars left. How could I make sure I am accessing the correct controller and label?
In your delegate protocol, define a way to send the UITextView instance along with anything else, something like:
#protocol UITextFieldValidationDelegate
- (BOOL) textField:(UITextField)tf textForValidation:(NSString *)newText;
#end
So that when the UITextFields call this, they pass themselves in for inspection by the delegate:
BOOL valid = [self.delegate textField:self textChanged:newText];
In the delegate, you'll implement this as:
- (BOOL) textField:(UITextField)tf textForValidation:(NSString *)newText
{
//compare to your IBOutlets
if (tf == self.tfPhoneNumber)
{
//Do phone number validation
}
else if (tf == self.tfEmail
{
//Do email validation
}
if (valid)
{
return YES;
}
else
{
return NO;
}
}
Add a tag to each textView, and check the tag in the delegate methods.
//In your viewcontroller setup
someTextView.tag = 0;
someOtherTextView.tag = 1;
someThirdTextView.tag = 2;
//In your delegate methods
if(textView.tag == 0)
//do something
else if(textView.tag == 1)
//do something else
else if(textView.tag == 2)
//do a third thing

dynamically change UIKeyboards return key

I have two UITextfield the user enters his name into the first and email into the second. I would like to know how to change the UIKeyboards return key depending if the name text field has an entry or not.
For instance if nametextfield is empty then I would like the UIkeyboard return key to be Next
else if the nametextfield has an entry in it then when the user selects the email text field I would like the return key to be submit.
Is this possible? if so how would I go about accomplishing it? any help would be appreciated.
You can have return key customized to prefixed values that you can see in UIReturnKeyType enum for each UITextField.
textFieldName.returnKeyType = UIReturnKeyNext;
textFieldEmail.returnKeyType = UIReturnKeyDefault;
Not sure if this is what you're looking for though.
You have a chance to set up keyboard characteristics in the UITextFieldDelegate Protocol method textFieldShouldBeginEditing: which is called before the text field becomes the first responder (indeed to decide if it may become the first responder). If you don't already have a delegate for the text field(s) in question you would have to assign one and implement at least that method. Presumably the same object handling the text field could hold the delegate methods. The following implementation sets the return key to "Search".
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"textFieldShouldBeginEditing");
textField.returnKeyType = UIReturnKeySearch;
return YES;
}
You'd have to look at the contents of your text fields to decide what value to use.
Make use of the textField.returnKeyType property.
you can check out all the available options here http://developer.apple.com/library/ios/documentation/uikit/reference/UITextInputTraits_Protocol/Reference/UITextInputTraits.html#//apple_ref/doc/c_ref/UIReturnKeyType
textfield.returnKeyType = UIReturnKeySearch;

Resources