Non-editable UITextField with copy menu - iphone

Is there a way to make a UITextField non-editable by the user and provide only a copy menu without subclassing? I.e when the text field is touched it automatically selects all the text and only shows the copy menu.
If possible to do this without subclassing what are the interface builder options that need to be selected?
Thanks in advance.

simply do:
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return NO;
}
and also:
yourTextField.inputView = [[UIView alloc] init];

You can disable editing by setting the enabled property of UITextField to NO.
textField.enabled = NO;
Note that doing this will also disable the copy/paste options.
What you are asking for has been discussed before in this solution: Enable copy and paste on UITextField without making it editable

Without subclassing, but also without auto-selection, i.e the user can select, keyboard shows up, but the user cannot input data:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return NO;
}

Items required to make a UITextField (in this case, outputTextField)
able to accept touch and allow Select, Select All, Copy, Paste, but
NOT edit the area and also DISABLE popup keyboard:
Put "UITextFieldDelegate" in angle brackets after ViewController declaration in #interface
In the -(void)viewDidLoad{} method add the following two lines:
self.outputTextField.delegate = self;
self.outputTextField.inputView = [[UIView alloc] init];
Add delegate method (see actual method below):
textField: shouldChangeCharactersInRange:replacementString: { }
// ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
// ViewController.m
#import "ViewController.h"
#interface ViewController () <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *inputTextField;
#property (weak, nonatomic) IBOutlet UITextField *outputTextField;
- (IBAction)copyButton:(UIButton *)sender;
#end
#implementation ViewController
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
NSLog(#"inside shouldChangeCharactersInRange");
if (textField == _outputTextField)
{
[_outputTextField resignFirstResponder];
}
return NO;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.outputTextField.delegate = self; // delegate methods won't be called without this
self.outputTextField.inputView = [[UIView alloc] init]; // UIView replaces keyboard
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)copyButton:(UIButton *)sender {
self.outputTextField.text = self.inputTextField.text;
[_inputTextField resignFirstResponder];
[_outputTextField resignFirstResponder];
}
#end

This worked for me to have UITextField non Editable and only allow copy. Just change your UITextField Class to CopyAbleTF from XIB and you are set.
#implementation CopyAbleTF
- (void)awakeFromNib{
self.inputView= [[UIView alloc] init];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == #selector(copy:))
{
return true;
}
return false;
}
- (void)copy:(id)sender {
UIPasteboard *board = [UIPasteboard generalPasteboard];
[board setString:self.text];
self.highlighted = NO;
[self resignFirstResponder];
}
#end

Related

Subclass of UITextField

I want to subclass UITextField and have a method that sets the maximum number of characters. allowed. In the init method of this subclass I try setting the inputDelegate to self but the callbacks aren't triggered. Also this is an iOS 5 thing only. My question is what protocol or notification would allow me to fire an event when a key is tapped so that I don't have to implement the UITextField delegate in my view controller to achieve this limit.
Thanks.
You could do it like this, create a delegate class for you textfield
.m file
#implementation LimitedTextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField.text.length >= 5 && ![string isEqualToString:#""])
return NO;
return YES;
}
#end
.h file
#interface LimitedTextFieldDelegate : UITextField<UITextFieldDelegate>
#end
in the UITextField subclass do the following
- (id)init
{
self = [super init];
if (self) {
//limitedDelegate is a property of your textfield subclass
self.limitedDelegate = [[LimitedTextFieldDelegate alloc] init];
self.delegate = self.limitedDelegate;
}
return self;
}

How to save data of the custom cell textfields?

i am new to the iPhone development, i am developing an app were i have tableview with custom-cell,my custom-cell contains label and textfiled. this is my registration screen,How to save the data of my textfields and,how to do validations for the text. In the textfield endediting we can save the data. but if the user on the first filed enter name and then he click done button it will show please enter first name, because i am saving data in didendediting. i want to save the data when ever user is on the textfield.
you can use this method to trace your current textfield text, with the help of the model class objects to store your text.
- (BOOL)textField:(UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString *characterSet = nil;
switch (theTextField.tag)
{
case 1:
characterSet = #"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
[sharedInstance.registrationDetails setFirstName:theTextField.text];
default:
characterSet = #"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?/!##$&*.,-:; _";
break;
}
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:characterSet];
for (int i = 0; i < [string length]; i++)
{
unichar c = [string characterAtIndex:i];
if (![myCharSet characterIsMember:c])
{
return NO;
}
}
return YES;
}
Make the controller the delegate of the cell's textField and then implement these methods in your controller.
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSInteger tag = [textField tag];
if(tag == 0) {
//save first name text value
}
else if (tag == 1){
//save last name text value
}
else if etc....
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Just make sure you set the tag appropriately when you return the cell in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
You could also do some research on how to get the keyboard to act like a form handler with the next/previous buttons
Register.h
#interface Register : NSObject {
NSString *_firstNameTxt;
NSString *_lastNameTxt;
NSString *_emailTxt;
NSString *_passwordTxt;
}
#property (nonatomic, retain) NSString * firstNameTxt;
#property (nonatomic, retain) NSString * lastNameTxt;
#property (nonatomic, retain) NSString * emailTxt;
#property (nonatomic, retain) NSString * passwordTxt;
#end
Register.m
#implementation Register
#synthesize firstNameTxt=_firstNameTxt;
#synthesize lastNameTxt =_lastNameTxt ;
#synthesize emailTxt=_emailTxt;
#synthesize passwordTxt= _passwordTxt;
- (void)dealloc{
[super dealloc];
[_firstNameTxt release];
[_lastNameTxt release];
[_emailTxt release];
[_passwordTxt release];
}
#end
RegisterViewController.h
#class Register;
#interface RegisterViewController : UIViewController {
Register *objRegister;
}
RegisterViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
objRegister = [[Register alloc] init];
}
tableview delegates
[txtFirstName setText:objRegister.firstNameTxt];
[txtLastName setText:objRegister.lastNameTxt];
-(void) textFieldDidEndEditing:(UITextField *)textField{
// do the same code as Warren Burton Post
}

How can I set didEndOnExit in code rather than Interface Builder? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Assign a method for didEndOnExit event of UITextField
How can I add didEndOnExit to a UITextField in pure code rather than IB?
Thanks!
Assuming your talking about textFieldDidEndEditing: or textFieldShouldReturn:. You would implement the method in your view controller, and set the text fields delegate to self like so:
- (void)viewDidLoad {
[super viewDidLoad];
// ....
myTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 50, 25)];
myTextField.delegate = self;
[self.view addSubview:myTextField];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField == myTextField) {
// Do stuff...
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == myTextField) {
return YES;
}
return NO;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ((myTextField.text.length + string.length) < 5) {
return YES;
}
return NO;
}
Then, in your header file in the #interface you can specify that you are a UITextFieldDelegate like this:
#interface MyViewController : UIViewController <UITextFieldDelegate> {
// ....
UITextField *myTextField;
// ....
}
// Optionally, to make myTextField a property:
#property (nonatomic, retain) UITextField *myTextField;
#end
UITextField Reference
UITextFieldDelegate Reference
Edit (as per your comment, this should work):
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ((myTextField.text.length + string.length) < 5) {
return YES;
}
return NO;
}

resignFirstResponder UITextView

I am using a UITEXTVIEW. I am trying to send a resignFirstResponder when the done button is pressed. I am not sure how to trigger the method containing the resignFirstResponder line.
I have set the UITextView's delegate to the File's Owner in Interface Builder. This is my viewcontroller's header and implementation file:
#import <Foundation/Foundation.h>
#import "Question.h"
#interface CommentQuestionViewController : UIViewController {
Question *question;
IBOutlet UILabel *questionTitle;
IBOutlet UITextView *inputAnswer; //this is the textview
}
#property (nonatomic, retain) UILabel *questionTitle;
#property (nonatomic, retain) Question *question;
#property (nonatomic, retain) UITextView *inputAnswer;
- (void) addButton:(id)sender isLast:(BOOL)last;
- (void) setQuestionId:(NSString*)quId withTitle:(NSString*)quTitle number:(NSString*)quNum section:(NSString*)sId questionType:(NSString*)qt;
#end
#import "CommentQuestionViewController.h"
#implementation CommentQuestionViewController
#synthesize questionTitle, question, inputAnswer;
- (void) addButton:(id)delegate isLast:(BOOL)last{
UIBarButtonItem *anotherButton;
anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStylePlain target:delegate action:#selector(finishQuestionnaire:)];
self.navigationItem.rightBarButtonItem = anotherButton;
[anotherButton release];
}
-(void)viewDidLoad{
//self.questionTitle.text = question.qTitle;
[[self questionTitle] setText:[question qTitle]];
[super viewDidLoad];
NSString *str = [NSString stringWithFormat:#"Question %#", [question qNumber]];
//self.title = str;
[self setTitle:str];
[str release];
}
-(void) setQuestionId:(NSString*)quId withTitle:(NSString*)quTitle number:(NSString*)quNum section:(NSString*)sId questionType:(NSString*)qt{
question = [[Question alloc]init];
[question setQId:quId];
[question setQTitle:quTitle];
[question setQNumber:quNum];
[question setSectionId:sId];
[question setQType:qt];
}
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void) textViewDidEndEditing:(UITextView*)textView{
[textView resignFirstResponder];
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[inputAnswer release];
[questionTitle release];
[question release];
[super dealloc];
}
You can try this:
–(BOOL)textView:(UITextView*)textView shouldChangeCharactersInRange:(NSRange)range replacementText:(NSString*)text {
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
else
return YES;
}
Of course, you won't be able to type actual carriage returns if you do this.
After looking at your source code, the link that I had posted is pointless. I thought you were talking about the done key on the keyboard. But now I see that you were talking about an instance UIButton on the navigation bar, right?
Your addButton:isLast: method is looking great so far, but I'd change it a bit so it adheres to the Apple HIG:
- (void)addButton:(id)delegate isLast:(BOOL)last
{
UIBarButtonItem *anotherButton;
anotherButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:delegate
action:#selector(finishQuestionnaire:)];
self.navigationItem.rightBarButtonItem = anotherButton;
[anotherButton release];
}
It's pretty much the same, except this one creates a button with the appropriate style.
Anyway, I don't see how the button is being added since addButton:isLast: is not being called in viewDidLoad:. Add the following line in your viewDidLoad:.
[self addButton:self isLast:NO];
last is redundant in your addButton:isLast: since it's not even being use so I just pass whatever (NO).
You're almost done, but if you press that button, your application would crash since finishQuestionnaire: is not implemented on self (CommentQuestionViewController). And since you want to dismiss the keyboard when the user presses your done button, that's where we will also resign your text view as first responder. Just add the following method:
- (void)finishQuestionnaire:(id)sender
{
[inputAnswer resignFirstResponder];
}
It's BOOL that's it..
- (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 please check the following things..
Whether your textView is connected to the textView property defined in your class.. (You can see this in your xib, with an arrow icon).
2.Check whether the textView delegate is written in your .h file.
#interface YourViewController : UIViewController <UITextViewDelegate>
3.Check whether the textView's delegate is assigned.
//set this in the viewDidLoad method
self.textView.delegate = self;
Check for new line character by this method.
-(NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet
Then check the length of the text, if it is one character length, then new line character is entered, not pasted.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
BOOL hasNewLineCharacterTyped = (text.length == 1) && [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location != NSNotFound;
if (hasNewLineCharacterTyped) {
[textView resignFirstResponder];
return NO;
}
return YES;
}

Keyboard Iphone

Is possible to know when the user touch the keyboard iphone? When the user touch some button from keyboard... :/
The easiest way is to use a TextField. Even is your UI Does not call for one, you can set it's frame to zero so it doesnt show up onscreen. Then you can get access to the keys pressed by using the text field's delegate callback methods.
- (void)viewDidLoad {
[super viewDidLoad];
//CGRectZero because we don't want the textfield to be shown onscreen
UITextField *f = [[UITextField alloc] initWithFrame:CGRectZero];
//We set the delegate so we can grab keypressed
f.delegate = self;
[self.view addSubview:f];
[f becomeFirstResponder]; //Show the keyboard
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if (string.length >0) {
NSLog(#"%# Pressed",string);
}
else {
NSLog(#"Backspcae pressed");
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSLog(#"return pressed");
return YES;
}
Note: to avoid a compiler warning, make sure in your .h file the class explicitly says it implements the UITextFieldDelegate protocal. ie:
#interface MyViewController : UIViewController <UITextFieldDelegate>