Search code examples
objective-cxcodeuibuttonnstimer

Why does the UIButton keep reverting back to its original state?


I have a button, that when pressed cycles between timezones and displays their times; I had to add an NSTimer so the time would update on the view.The problem is when I press the button, the second time zone time is shown but then goes away a second later and is replaced by the first time zone. I think this has to do with the NSTimer since when I comment it out, the button works fine but the times don’t update. Any help would be appreciated. Here's my code:

Creating the Button

UIButton *changeZone = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    changeZone.center = CGPointMake(250, 515);
    [changeZone addTarget:self action:@selector(changeZone:) forControlEvents:UIControlEventTouchUpInside];
    [changeZone setTitle:@"" forState:UIControlStateNormal];
    [self.view addSubview:changeZone];

Setting the base TimeZone and NSTimer

[formatter setDateStyle:NSDateFormatterShortStyle];
    [formatter setDateFormat:@"hh:mm"];

    self.zoneName.text = (@"NYC");
    NSString *strSelectedDate= [formatter stringFromDate:date];
    self.zone.text = strSelectedDate;
    [NSTimer scheduledTimerWithTimeInterval:1.0
                                     target:self
                                   selector:@selector(updateTime:)
                                   userInfo:nil
                                    repeats:YES];

Adding the button action and configuring the NSTimer

- (void)changeZone:(UIButton *) sender {

    if (_isTimeZone) {
        NSDate *date = [NSDate date];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateStyle:NSDateFormatterShortStyle];
        [formatter setDateFormat:@"hh:mm"];
        [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
        self.zoneName.text = (@"NYC");
        NSString *strSelectedDate = [formatter stringFromDate:date];
        self.zone.text = strSelectedDate;
        _isTimeZone = NO;
    } else {
        NSDate *date = [NSDate date];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateStyle:NSDateFormatterShortStyle];
        [formatter setDateFormat:@"hh:mm"];
        [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/London"]];
        self.zoneName.text = (@"LON");

        NSString *strSelectedDate = [formatter stringFromDate:date];
        self.zone.text = strSelectedDate;
        _isTimeZone = YES;

    }
}

- (void)updateTime:(id)sender {
    dispatch_async(dispatch_get_main_queue(), ^{
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateStyle:NSDateFormatterShortStyle];
    [formatter setDateFormat:@"hh:mm"];
    NSString *strSelectedDate = [formatter stringFromDate:date];
    self.zone.text = strSelectedDate;
    });
}

Solution

  • The formatter that you create in the timer's method, doesn't know anything about the time zone that you set with your button, because you're creating a new formatter. Use the ivar instead of creating a new one, and only change the one thing that's different, the time zone.

    @interface ViewController ()
    @property (weak,nonatomic) IBOutlet UILabel *zone;
    @property (weak,nonatomic) IBOutlet UILabel *zoneName;
    @property (nonatomic) BOOL isTimeZone;
    @end
    
    @implementation ViewController {
        NSDateFormatter *formatter;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        UIButton *changeZone = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
        changeZone.center = CGPointMake(250, 515);
        [changeZone setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [self.view addSubview:changeZone];
    
        [changeZone addTarget:self action:@selector(changeZone:) forControlEvents:UIControlEventTouchUpInside];
        [changeZone setTitle:@"Change Zone" forState:UIControlStateNormal];
    
        formatter = [NSDateFormatter new];
        [formatter setDateStyle:NSDateFormatterShortStyle];
        [formatter setDateFormat:@"hh:mm"];
    
        NSDate *date = [NSDate date];
        self.zoneName.text = (@"NYC");
        NSString *strSelectedDate= [formatter stringFromDate:date];
        self.zone.text = strSelectedDate;
        [NSTimer scheduledTimerWithTimeInterval:1.0
                                         target:self
                                       selector:@selector(updateTime:)
                                       userInfo:nil
                                        repeats:YES];
    
        NSLog(@"%@",self.zoneName);
    
    }
    
    - (void)changeZone:(UIButton *) sender {
    
        if (_isTimeZone) {
            NSDate *date = [NSDate date];
            [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
            self.zoneName.text = (@"NYC");
            NSString *strSelectedDate = [formatter stringFromDate:date];
            self.zone.text = strSelectedDate;
            _isTimeZone = NO;
        } else {
            NSDate *date = [NSDate date];
            [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/London"]];
            self.zoneName.text = (@"LON");
    
            NSString *strSelectedDate = [formatter stringFromDate:date];
            self.zone.text = strSelectedDate;
            _isTimeZone = YES;
    
        }
    }
    
    
    - (void)updateTime:(NSTimer *) timer {
            NSDate *date = [NSDate date];
            NSString *strSelectedDate = [formatter stringFromDate:date];
            self.zone.text = strSelectedDate;
    
    }