How can I get rid of “ghost” text that appears in UITextField after clearing the field programmatically?

StackOverflow https://stackoverflow.com/questions/6392525

Pergunta

I have a strange problem with a UITextField - I am setting the value of it to @"" (or anything else still causes it) and then shrinking the field with to zero. Next time I unshrink it, it displays the same value it had before I shrunk it, regardless of my having changed the text in the view. Typing in the field causes the glitch to go away, but it looks bad.

Image showing the problem

Complete code to reproduce:

throwaway_testViewController.h:

#import <UIKit/UIKit.h>

@interface throwaway_testViewController : UIViewController <UITextFieldDelegate>{



    UITextField * unitField;
}

@property (nonatomic, assign) IBOutlet UITextField * unitField;



-(IBAction)setEditingSectionUnits;
-(void)setEditingSectionValue;

-(IBAction)equalsPress;

@end

throwaway_testViewController.m

#import "throwaway_testViewController.h"

@implementation throwaway_testViewController

@synthesize unitField;

#pragma mark - Inputs

-(IBAction)equalsPress{
    [UIView animateWithDuration:0.5 animations:^(void){
        [unitField setText:@""];
        [self setEditingSectionValue];
    }];
}


#pragma mark Input Control

-(void)setEditingSectionUnits{
    [UIView animateWithDuration:0.5 animations:^(void){
        CGRect newRect = unitField.frame;
        newRect.size.width = 160;
        unitField.frame = newRect;
    }completion:^(BOOL completed){
        completed ? [unitField setNeedsDisplay] : nil;
    }];

    [unitField becomeFirstResponder];
}

-(void)setEditingSectionValue{
    [UIView animateWithDuration:0.5 animations:^(void){
        CGRect newRect = unitField.frame;
        newRect.size.width = [unitField.text sizeWithFont:unitField.font constrainedToSize:CGSizeMake(80, 250)].width;;
        unitField.frame = newRect;
    }completion:^(BOOL completed){
        completed ? [unitField setNeedsDisplay] : nil;
    }];

    [unitField resignFirstResponder];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [self setEditingSectionValue];
    return TRUE;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField{
    [self setEditingSectionUnits];
}


@end

In the xib, place a UITextField tied to unitField, and set the delegate of the text field to be file's owner.

Place a UIButton labeled equalsPress and tie it to that IBAction, and another called edit, tied to setEditingSectionUnits. To see the bug reproduced:

  • Run the app
  • Press edit
  • type something into the text field (min 8-10 characters)
  • press enter on the keyboard
  • press equalsPress
  • press edit
  • Should see: cursor and empty text field
  • Actually see: whatever you typed last, with a cursor at the start.
  • Typing makes this text disappear.
Foi útil?

Solução

after replicating your code, i found that the problem you mentioned occurs only if you press return on the keyboard and then tap the equals press button... resigning first responder before calling animation block in your setEditingSectionValue method resolved the problem:

-(void)setEditingSectionValue{
    [unitField resignFirstResponder];
    [UIView animateWithDuration:0.5 animations:^(void){
        CGRect newRect = unitField.frame;
        newRect.size.width = [unitField.text sizeWithFont:unitField.font constrainedToSize:CGSizeMake(80, 500)].width;;
        unitField.frame = newRect;
    }completion:^(BOOL completed){
        completed ? [unitField setNeedsDisplay] : nil;
    }];
}

Outras dicas

I am having trouble replicating your issue I have mocked this up to use the same sort of mechanisms as you and it works as expected.

- (void)viewDidLoad
{
  [super viewDidLoad];
  [self.unitField setText:@"Testing"];
}

- (IBAction)hideButtonTapped:(id)sender
{
  [UIView animateWithDuration:0.5 animations:^(void)
    {
      [self.unitField setText:@""];
      self.unitField.frame = CGRectMake(10, 10, 0, 30);
    }
  ];
}

- (IBAction)showButtonTapped:(id)sender
{
  [UIView animateWithDuration:0.5 animations:^(void)
    {
      self.unitField.frame = CGRectMake(10, 10, 100, 30);
    }
  ];
}

Perhaps you can give more of your code as I feel you may have omitted something important or you can point out where you implementation differs to the above.

I came up with a solution to your problem, its not nice, but at least its working :D

-(IBAction)equalsPress{
      tmp = nil;
      //same code as yours
}

-(void)setEditingSectionUnits{  
    if (tmp != nil) {
        unitField.text = tmp;
    }
    //same code as yours
}

-(void)setEditingSectionValue{
    if ([unitField.text length] > 9) {
            tmp = unitField.text;
            unitField.text = [unitField.text substringToIndex:9];
            [tmp retain];
    }else {
           tmp = nil;
    }
    //same code as yours
}

I declared tmp in the header file:

NSString *tmp;

I had a quick look but can you try retaining UITextField:

@property (nonatomic, retain) IBOutlet UITextField * unitField;

Also equalsPress can be

-(IBAction)equalsPress{
    [unitField setText:@""];
    [UIView animateWithDuration:0.5 animations:^(void){
        [self setEditingSectionValue];
    }];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top