I have two buttons for adding and deleting the textfields. Adding works fine but when I click on delete it deletes only the last added textfield. Here are my two methods:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
}
-(void)deleteTextField {
[keyTextField removeFromSuperview];
[valueTextField removeFromSuperview];
yAxisDistance = yAxisDistance-35;
}
I know it's an small issue but I am very new to this field so kindly help.
Use this code for remove specific textfield from UIView. But First you have to set tag of every UITextField in view when you create or add it in view.
for ( UITextField* textField in view.subviews )
{
if(textField.tag== 1)
{
[textField removeFromSuperview];
}
}
I think the problem lies with the outlet. Can you check the following:
Open the outlets that are connected to the textifeld in the IB. There should be gray dots inside circles on the left side of the editor. Are they seem correct for both text fields?
Setup a breakpoint inside deleteTextField method and check the two textfields. Verify that both properties are not nil.
PS: You don't need to add tags to your view, using properties is perfectly fine and even better in my opinion. The reason for your problem is something else. Also, you do not need to removeFromSuperview, you can also setHidden:YES.
Sorry that time I was not understand your problem...
I done with this:
Declare one
NSMutableArray *allTextfieldArray;
and initialise in
viewdidload
method..
now do:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
[allTextfieldArray addObject:keyTextField];
[allTextfieldArray addObject:valueTextField];
}
if ([allTextfieldArray count]>0) {
UITextField *txtField = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField removeFromSuperview];
txtField = nil;
UITextField *txtField2 = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField2 removeFromSuperview];
txtField2 = nil;
yAxisDistance = yAxisDistance-35;
}
you store the last textField in your variables keyTextField and valueTextField. So when you call your deleteTextField the last both will be deleted. you must track which textFileds you want exactly to delete.
for example you could give all your textFields a tag number when you create them:
first create an int as counter:
#implementation YourClass {
int tagcounter;
}
in init method set your counter:
tagcounter = 0;
in your addTextField:
keyTextField.tag = tagcounter++;
valueTextField.tag = tagcounter++;
when the delete button is tapped, you must know the textfield tags and pass them to your deleteTextField method. There you could do something like:
-(void)deleteTextFieldWithTag:(int)tagnumber {
for (UIView *view in [self.view subviews])
{
if ([view isKindOfClass:[UITextField class]])
{
if (view.tag == tagnumber || view.tag == tagnumber+1) {
[view removeFromSuperview];
}
}
}
Related
I am using the following code to attach gesture recognizers to a custom view. But for some reason I am not able to get the gestures to work.
for(NSString *option in _options) {
UIView *blind = [self createBlind:option];
blind.userInteractionEnabled = YES;
blind.tag = index;
[self addSubview:blind];
[self addGravityBehaviorToBlind:blind];
[self addCollisionBehaviorToBlind:blind];
[self addElasticityBehaviorToBlind:blind];
[self registerGestureRecognizer:blind];
_spacingY += 44;
index++;
}
}
-(void) registerGestureRecognizer:(UIView *) blind {
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(blindTapped:)];
[blind addGestureRecognizer:tapGestureRecognizer];
}
-(void) blindTapped:(UITapGestureRecognizer *) recognizer { <-- THIS NEVER GETS CALLED
NSLog(#"blindTapped");
}
For some reason the blindTapped method never gets called even if I tap on the blind view.
UPDATE:
Yes, I see the views on the screen. The views (blind) is a subview in another view. The parent view gets added to the controller.view. There is no place where I have disabled interaction.
Here is the createBlind method:
-(UIView *) createBlind:(NSString *) option {
UIView *blind = [[UIView alloc] initWithFrame:CGRectMake(0, _spacingY, 200, 44)];
blind.layer.borderWidth = 1.0f;
blind.layer.borderColor = [UIColor whiteColor].CGColor;
UILabel *optionTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, blind.bounds.size.width, blind.bounds.size.height)];
optionTitleLabel.text = option;
optionTitleLabel.font = [UIFont fontWithName:#"GillSans" size:17];
optionTitleLabel.textColor = [UIColor whiteColor];
optionTitleLabel.textAlignment = NSTextAlignmentCenter;
[blind addSubview:optionTitleLabel];
return blind;
}
I have removed all the gravity and UIKit methods but still I am not able to trigger the tap gesture.
SOLUTION:
When adding the custom view to my controller.view I was not setting the frame. Once the frame was setup everything worked.
vwInfo = [[UIView alloc]initWithFrame:CGRectMake(20, 85, 280, 100)];
[self.view addSubview:vwInfo];
I create a UIView programmatically on button tap.when i click it again i need to check vwInfo is visible or not.I can done this with a Boolean value.is there any other option to do this?
you can check if view is exist or not using isDescendantOfView but make sure you have to pass your vwInfo's superview to check view already exist or not.
if ([vwInfo isDescendantOfView:self.view]) {
//view already exist in self.view
}
else{
//view is not exist in self.view.
}
Is it because you do not want to add the UIView a second time when you already added it ?
In this case you could declare in your .h(header) file UIView *vwInfo;
and then in your IBAction for your UIButton:
if(vwInfo == nil) {
vwInfo = [[UIView alloc]initWithFrame:CGRectMake(20, 85, 280, 100)];
[self.view addSubview:vwInfo];
}
you can check with Tag Functionality. Assign tag to your view.
UIView * vwInfo = [[UIView alloc]initWithFrame:CGRectMake(20, 85, 280, 100)];
[vwInfo setTag:101];
[self.view addSubview:vwInfo];
On Button Click
- (void)buttonClick :(id)sender {
UIView * viewTemp = (UIView *)[self.view viewWithTag:101];
if(viewTemp){
NSLog(#"View is available");
if([viewTemp isHidden]){
NSLog(#"Your view is hidden");
}else{
NSLog(#"Your view is visible");
}
}else{
NSLog(#"View is not added yet");
}
}
UIView is accessible with the superview property
if([vwInfo superview]!=nil)
NSLog(#"visible");
else
NSLog(#"not visible");
I'm new to iOS development and I have an assignment where I need to implement a a UITextfield which upon a tap, brings a country selector UIPickerView.
I went through some online tutorials and got it working somehow. But it shows some strange behaviour which I can't seem to figure out.
Some strange black bars are appearing, with the picker content visibly duplicated each time I scroll.
I believe I've made a mistake in my code, forgive my lack of knowledge but can't seem to figure out what is wrong in the code.
Could you please tell me what has gone wrong?
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if ([textField isEqual:self.countryTextField]) {
countryPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
countryPicker.showsSelectionIndicator = YES;
self.countryPicker.delegate = self;
self.countryPicker.dataSource = self;
// [self.countryPicker reloadAllComponents];
countryPicker.showsSelectionIndicator = YES;
// [countryPicker init:self];
textField.inputView = countryPicker;
}
return YES;
}
- (UIView * ) pickerView: (UIPickerView * ) pickerView viewForRow: (NSInteger) row forComponent: (NSInteger) component reusingView: (UIView * ) view {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.text = [NSString stringWithFormat:#"%#", [[self.countries objectAtIndex:row] objectForKey:#"name"]];
[label setTextAlignment:UITextAlignmentLeft];
[label setBackgroundColor:[UIColor clearColor]];
[label setFont:[UIFont boldSystemFontOfSize:15]];
return label;
}
Might be initialising every time , instead of initialising at every time , Check whether the UIPicker is already initialised
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if ([textField isEqual:self.countryTextField]) {
if(! countryPicker){
countryPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
countryPicker.showsSelectionIndicator = YES;
self.countryPicker.delegate = self;
self.countryPicker.dataSource = self;
countryPicker.showsSelectionIndicator = YES;
}
textField.inputView = countryPicker;
}
return YES;
}
It seems there are few things need to be changed in your code
1.Don't allocate memory to UIPickerView every time your text field get edited -textFieldShouldBeginEditing
if(self.countryPicker == nil)
{
self.countryPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
self.countryPicker.showsSelectionIndicator = YES;
self.countryPicker.delegate = self;
self.countryPicker.dataSource = self;
self.countryPicker.showsSelectionIndicator = YES;
}
2.Either use self.countrypicker -> class property or countrypicker don't use them interchangeably.
Well I finally found the issue. It was a silly mistake of defining a wrong number of components in numberOfComponentsInPickerView
Have been searching alot for this, but I think I'm doing something stupidly wrong. I have a lot of labels on my second screen, and they all have the same properties. That's why I create them via a method.
In ViewDidLoad I do this:
[self screenTwoLabelMaker:firstNameLabel withFrame:CGRectMake(30, 200, 200, 40) withText:#"First Name"];
That method is this one:
- (UILabel *)screenTwoLabelMaker:(UILabel *)sender withFrame:(CGRect)frame withText:(NSString *)text
{
sender = [[UILabel alloc] init];
sender.text = text;
sender.frame = frame;
sender.font = [UIFont systemFontOfSize:labelFontSize];
sender.textColor = [UIColor grayColor];
[self.scrollView addSubview:sender];
return sender;
}
Then I do this:
NSLog(#"firstNameLabel x: %f y:%f w:%f h:%f", firstNameLabel.frame.origin.x, firstNameLabel.frame.origin.y, firstNameLabel.frame.size.width, firstNameLabel.frame.size.height);
But the result is this:
MyApp[9608:60b] firstNameLabel x: 0.000000 y:0.000000 w:0.000000 h:0.000000
The weird thing is that the label is being put on the screen on the right place with the right text. So everything should be sunny and warm, no? Well, I also call a similar method for buttons, where there is a tag included. That tag is never active on the button (nil), so further programming for that button is killing me. For now I create them all by hand. Do you guys know what I'm doing wrong?
Your method returns your new label, so you need to assign it to the variable that you want to hold the reference. You don't need to pass in the variable to the method as the first thing you do is overwrite it. Use the following code -
firstNameLabel = [self screenTwoMakeLabelwithFrame:CGRectMake(30, 200, 200, 40) text:#"First Name"];
- (UILabel *)screenTwoMakeLabelwithFrame:(CGRect)frame text:(NSString *)text
{
UILabel newLabel = [[UILabel alloc] init];
newLabel.text = text;
newLabel.frame = frame;
newLabel.font = [UIFont systemFontOfSize:labelFontSize];
newLabel.textColor = [UIColor grayColor];
[self.scrollView addSubview:newLabel];
return newLabel;
}
How do I create and add multiple UITextField to my controller?
I can create one, like this:
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5,5,100,25)];
tf.borderStyle = UITextBorderStyleRoundedRect;
[tf setReturnKeyType:UIReturnKeyDefault];
[tf setEnablesReturnKeyAutomatically:YES];
[tf setDelegate:self];
[self.view addSubview:tf]
But do I need to do that for each UITextField?
Whats the best approach to template UI Controls?
Put it in a loop, offset each text field's Y position and tag each text field:
for (int i = ; i < numberOfTextFieldsNeeded; i++) {
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(5, 5 + 35 * i ,100,25)]; // 10 px padding between each view
tf.tag = i + 1; // tag it for future reference (+1 because tag is 0 by default which might create problems)
tf.borderStyle = UITextBorderStyleRoundedRect;
[tf setReturnKeyType:UIReturnKeyDefault];
[tf setEnablesReturnKeyAutomatically:YES];
[tf setDelegate:self];
[self.view addSubview:tf]
// don't forget to do [tf release]; if not using ARC
}
Then in delegate methods perform actions based on tag of the textField that called each delegate method. For example to switch to next text view when user taps return key:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
UITextField *nextTextField = [self.view viewWithTag:textField.tag + 1];
[nextTextField becomeFirstResponder];
}
Keep in mind that sending messages to nil in Objective-C will not crash so it will be perfectly fine when user taps return key in last text field as UITextField *nextTextField = [self.view viewWithTag:textField.tag + 1]; will return nil, and calling becomeFirstResponder on nil will do nothing. But you can check if nextTextField is nil and do something else then, whatever you like.
You can use interface builder to create a view (bigger than the size that the screen fits) and programmatically add it to a scrollView.
This is in my opinion the best approach.