I am trying to make a custom TextField (KSTextField). I inherited my text field from UITextField. As you can see my KSTextField.h file below.
#import <UIKit/UIKit.h>
#import <UIKit/UITextField.h>
#interface KSTextField : UITextField {}
#end
In my KSTextField.m i tried to set a dummy text attribute. But it doesn't work. Is super.text usage wrong?
My main purpose is, making a custom UITextField that only allows for upper case characters which is needed for my project.
#import "KSTextField.h"
#implementation KSTextField
- (id)init {
self = [super init];
super.text = #"help";
return self;
}
- (void)textFieldDidChangeForKS:(KSTextField *)textField {
self.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
NSString *textToUpper = [textField.text uppercaseString];
[self setText:textToUpper];
}
#end
And also mine ViewController.h is below
#import <UIKit/UIKit.h>
#import "KSTextField.h"
#interface ViewController : UIViewController
#property (nonatomic, copy) IBOutlet KSTextField *txtKsName;
#end
Here's my ViewController.m which i want to set my KSTextField.text
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.txtKsName = [[KSTextField alloc] init];
}
Delegate events do not solve my issue. Because i'll add much more features later. It will be my custom textfield thanks!
The answer is: you're doing it wrong! You don't have to subclass to allow uppercase characters only. Use a UITextFieldDelegate:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextFieldDelegate_Protocol/UITextFieldDelegate/UITextFieldDelegate.html
Using the textField:shouldChangeCharactersInRange:replacementString: method, you can say whether on not the character typed is allowed to be added to the box.
Try something like this:
- (BOOL)textField:(UITextField *)field shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)characters
{
NSCharacterSet *blockedCharacters = [[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet] retain];
return ([characters rangeOfCharacterFromSet:blockedCharacters].location == NSNotFound);
}
Related
I want to validate UITextField input for multiple view controllers. The following works:
validate.h
#import <UIKit/UIKit.h>
#interface validate : UITextField <UITextFieldDelegate>
#end
validate.m
#import "validate.h"
#implementation validate
viewController.h
#import <UIKit/UIKit.h>
#include "limiteTextField.h"
#interface ViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet limiteTextField *myTextField;
#end
viewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//my code for validating
}
- (void)viewDidLoad {
[super viewDidLoad];
_myTextField.delegate=self;
I want to be able to use the shouldChangeCharactersInRange as an external function so don't have to rewrite all its code for each view controller.
I want to be able to use the shouldChangeCharactersInRange as an external function so don't have to rewrite all its code for each view controller.
Then do so. This is a delegate method. Anything can be the delegate. You are the one who is setting the text field's delegate to be different view controllers! If you don't want to do that, then don't. Have some single persistent object, or at least multiple instance of the same class, and make that the delegate of the text field. Now all text fields can use this same delegate which has just one implementation of shouldChangeCharactersInRange.
One approach is to create some kind of validator class with a singleton and assigning it as the textfields delegate:
TextFieldValidator.h
#import <UIKit/UIKit.h>
#interface TextFieldValidator : NSObject <UITextFieldDelegate>
+ (instancetype)sharedValidator;
#end
TextFieldValidator.m
#import "TextFieldValidator.h"
#implementation TextFieldValidator
+ (instancetype)sharedValidator {
static TextFieldValidator *sharedValidator = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedValidator = [[self alloc] init];
});
return sharedValidator;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *allowedCharacters = [NSCharacterSet decimalDigitCharacterSet];
return [[textField.text stringByReplacingCharactersInRange:range withString:string] rangeOfCharacterFromSet:allowedCharacters.invertedSet].location == NSNotFound;
}
#end
SomeViewController.m
// [...]
self.textField.delegate = [TextFieldValidator sharedValidator];
// [...]
I am a new ios developer, I want to create a new class inherit from NSObject, and it reference a UITextField. it has a property "maxLength" which limits the characters length of the UITextField, then I make the UITextField's delegate as this class"self.textField.delegate=self", and implement the method "textField:shouldChangeCharactersInRange:replacementString:",but when it didn't work, anyone can tell me why? thanks in advance
the code is given below:
#interface TextEditor : NSObject<UITextFieldDelegate>
///limit the characters length in the textfield
#property (nonatomic,assign) NSUInteger maxLength;
///reference a textField
#property (nonatomic,strong) UITextField *textField;
-(id)initWithFrame:(CGRect)frame;
#end
#implementation TextEditor
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (self.textField==textField) {
if (string.length==0) {
return YES;
}
if (textField.text.length-range.length+string.length>_maxLength) {
return NO;
}
}
return YES;
}
-(id)initWithFrame:(CGRect)frame
{
if (self=[super init]) {
_textField=[[UITextField alloc] initWithFrame:frame];
_textField.borderStyle=UITextBorderStyleRoundedRect;
_textField.delegate=self;
}
return self;
}
#end
In the ViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
TextEditor *te=[[TextEditor alloc] initWithFrame:CGRectMake(50, 270, 200, 50)];
te.maxLength=10;
[self.view addSubview:te.textField];
}
The TextEditor object is declared as local variable inside the viewDidLoad method. This object will be destroyed as long as you leave the viewDidLoad method. The TextEditor object's scope should be maintained until the textField object is destroyed or removed from it's superview. To achieve this, we can make the TextEditor object as instance variable or property.
The code will be changed to
#interface ViewController ()
{
TextEditor *te;
}
- (void)viewDidLoad {
[super viewDidLoad];
te = [[TextEditor alloc] initWithFrame:CGRectMake(50, 270, 200, 50)];
te.maxLength = 10;
[self.view addSubview:te.textField];
}
Like this way your delegate method will not get called. so confirm this in your viewcontroller class and write define delegate method in your viewController.m
No need to do like this.
Second thing if you want custom class for textfield then you should subclass UITextfield not NSObject. This will add UIkit in your class also.
hope this will help :)
This question already has answers here:
Type in two uitextfield at the same time
(2 answers)
Closed 8 years ago.
If I am going to enter text in first UITextField that automatically should display in second UITextField. In my case I already tried with all UITextFieldDelegate methods but if I am entering a in first UITextField I am getting a alone in second UITextField, I am getting lesser then one character.
But I Need it like if I am going type ABCDEF..... IN UITextFielD 1 IN UITextField 2 also it should be print like ABCDEF.....typing should be continued text also should be continued.
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
UITextField2.text = UITextField1.text;
UITextField.text = textField.text;
}
I tried like this but not worked out. Thanks in Advance.
Try this..
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([textField isEqual:UITextField1]){
UITextField2.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
}
return YES;
}
Instead of using shouldChangeCharactersInRange:, I use a different technique to handle text changes in UITextFields. It is similar to the textViewDidChange: method of UITextView.
You add behaviour using:
[textField1 addTarget:self action:#selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
Then in the target method :
- (void) textFieldDidChange {
textField2.text = textField1.text;
}
That's it. The advantage here, besides avoiding observers, is that you handle text changes after it actually changes.
Objects used:
UITextField *txtFFirst;
changes in txtFFirst propagate to txtFSecond
UITextField *txtFSecond;
Possible ways:
UITextFieldTextDidChangeNotification notification
or...
UIControlEventEditingChanged control event
- (void)viewDidLoad
{
//...
//[1] Notification Method
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(textFieldDidChangeByNotification:)
name:UITextFieldTextDidChangeNotification
object:txtFFirst];
//OR... (uncomment the following and comment the above)
//[2] Control Event Method
//[txtFFirst addTarget:self
// action:#selector(textFieldDidChangeByControlEvent:)
// forControlEvents:UIControlEventEditingChanged];
}
//[1] Fires when the Notification Method is used
-(void)textFieldDidChangeByNotification:(NSNotification *)note
{
UITextField *txtFTemp = [note object];
[txtFSecond setText:txtFTemp.text];
}
//[2] Fires when Control Method is used
-(void)textFieldDidChangeByControlEvent:(UITextField *)sender
{
[txtFSecond setText:sender.text];
}
Try This code:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITextFieldDelegate>
#property (nonatomic,strong) IBOutlet UITextField *name;
#property (nonatomic,strong) IBOutlet UITextField *sameName;
#end
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize name,sameName;
- (void)viewDidLoad
{
name.delegate = self;
sameName.delegate = self;
[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.
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([textField isEqual:name]){
sameName.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
}
return YES;
}
#end
I am trying to store and load some text from global variable in x-code. I declare it in main.m, outside of the main function. Then when I want to access it, I use extern. The application crashes after I click the saveButton second time with text in it. It seems like there would be some error rewriting the global labelString string. Can you figure this puzzle out please?
EDIT: Thanks to BKC, I have made some minor changes in the code, however I still get the same error. The code is updated.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (retain, nonatomic) IBOutlet UITextField *field;
- (IBAction)saveButton:(id)sender;
FOUNDATION_EXPORT NSString *labelString;
FOUNDATION_EXPORT NSString *separator;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize field;
NSString *labelString = #"";
NSString *separator = #"|<->|";
- (IBAction)saveButton:(id)sender {
if([field.text length] != 0) // if field isn't blank
{
if([labelString length] == 0) // nothing stored in labelString
{
labelString = field.text;
}
else // if something is already stored in labelString
{
NSString *str = [NSString stringWithFormat:#"%#%#%#", labelString, separator, field.text];
labelString = str;
}
field.text = #"";
}
}
- (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)dealloc {
[field release];
[super dealloc];
}
#end
Thank you.
The way you are defining the variable isn't right way. i use any global variable in my project something like this..
Declare the variable in .h file
FOUNDATION_EXPORT NSString *labelString; // Use extern if mixing with C++
Define the varibale in .m file
NSString *labelString = #"";
Include the header wherever you want to use that. i think in your code its crashing because of multiple time definition of labelString variable.
I am new to iPhone development, I have a program that has 7 UITextFields visableenter code here. When the user picks a number on the UIPicker View (1-5) that many UITextFields become hidden and unusable. That program works well. I want to have the same number that was picked from that .m file and transfered to another .m file so that 1-5 UITextFields are hidden and unusable. If it matters, the first .m file is abc.m and the second one is bca.m
if it matters I use [textfield sethidden= YES]
Thanks
You need to keep references to all those objects in the class, and define properties to them so that you can refer to them in the second .m file.
So assuming you have a classes, abc.m
#interface abc {
UITextField *text1;
}
#property (nonatomic, retain) UITextField *text1;
#end
#implementation abc
#synthesize text1;
- (id) init {
if (self = [super init]) {
text1 = [[UITextField alloc] initWithFrame:CGRectMake(0,0,150,10)];
}
return self;
}
- (void)dealloc {
[text1 release];
[super dealloc];
}
Then you can use the text1 property to refer to that text field, given that you have instantiated the object in the second class, or hold a reference to it.
[[MyClass alloc] initWithFrame: CGRectZero andSomeString: #"Hello World!"];
MyClass
- (id)initWithFrame:(CGRect)frame andSomeString:(NSString*)aString
{
if (self = [super initWithFrame:frame])
{
someString = aString;
}
return self;
}
You could try making a BOOL or several BOOL variables and set it equal to YES or NO then put that into your text fields.
BOOL isVisible = YES;
[textfield setHidden:isVisible];
and then if you use a pushViewController you can set the isVisible from bca.m equal to the isVisible in abc.m
viewController.isVisible = isVisible;