NSTimer 和 NSDateFormatter 麻烦.我的计时器标签在刷新时消失



我在一个视图控制器上有一个UIDatePicker,它允许用户以(7月22日星期日下午2:33)的形式设置日历日期,小时和分钟,以便在单独的viewController中使用计时器。在单独的视图控制器上,我试图让计时器以"dd:hh:mm:ss"的形式显示在UIImagePickerController的叠加层中,在当前NSDate(今天的日期/时间)和选定的日期选择器日期之间。基本上,它是一个倒数计时器,当相机加载时,它会从所选选择器日期开始倒计时天、小时、分钟、秒。我的问题是,一旦相机加载,计时器就会以正确的格式显示正确的剩余时间,但在进入我的 refreshLabel 方法时会迅速消失。我记录了我的 timerLabel 的值,它在日志中正确显示,但一旦循环运行,它就会为所有内容返回 Null。昨晚我在确定我的问题很可能与字符串中的日期格式有关方面得到了一些帮助,但我看不出可能出错的地方是什么,因为相机首次加载时最初会显示正确的日期。所以这是我的第一个视图控制器的代码,带有设置计时器标签时间的日期选择器:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showDate"]) {
        NSString *textFieldContents = self.textField.text;
        NSString *counterContents = self.counter;
        NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *deadline = [NSString stringWithFormat:@"%@/deadline.txt",
                              documentsDirectory];
        NSString *flashName = [NSString stringWithFormat:@"%@/flashName.txt",
                               documentsDirectory];
        NSError *fileError;
        [textFieldContents writeToFile:flashName
                            atomically:YES
                              encoding:NSStringEncodingConversionAllowLossy
                                 error:&fileError];
        [counterContents writeToFile:deadline
                           atomically:YES
                             encoding:NSStringEncodingConversionAllowLossy
                                error:&fileError];
        if(fileError.code == 0){
            NSLog(@"deadline.txt was written successfully with these contents: %@,", 
                  counterContents);
            NSLog(@"flashName.txt was written successfully with these contents: %@,",
                  textFieldContents);}
        else
            [self performSegueWithIdentifier:@"showDate" sender:self];}
}
-(IBAction)refreshLabel; {
        NSDate *selected = [NSDate dateWithTimeIntervalSince1970:[picker.date timeIntervalSince1970] - 1];
        self.counter = [self.formatter stringFromDate:selected];
        NSLog(@"selected is: %@", selected);
        NSDate *todaysDate = [NSDate date];
        NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
        NSUInteger unitFlags = NSDayCalendarUnit | NSMinuteCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit;
        NSDateComponents *dateComparisonComponents = [gregorian components:unitFlags fromDate:todaysDate toDate:selected options:NSWrapCalendarComponents];
        NSInteger days = [dateComparisonComponents day];
        NSInteger hours = [dateComparisonComponents hour];
        NSInteger minutes = [dateComparisonComponents minute];
        NSInteger seconds = [dateComparisonComponents second];
        self.counter = [NSString stringWithFormat:@"%ld:%02ld:%02ld:%02ld", (long)days, (long)hours, (long)minutes, (long)seconds];
        NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        NSString *deadline = [NSString stringWithFormat:@"%@/deadline.txt", documentsDirectory];
        NSInteger success = [NSKeyedArchiver archiveRootObject:selected toFile:deadline];
        NSLog(@"success is: %d",success);
    }e *selected = [NSDate dateWithTimeIntervalSince1970:[[picker date] timeIntervalSince1970] - 1];
- (void)viewDidLoad
{   [super viewDidLoad];
    self.textField.delegate = self;
    self.formatter = [NSDateFormatter new];
    [self.formatter setDateFormat:@"dd:hh:mm:ss"];
    NSDate *now = [NSDate date];
    picker.minimumDate = [NSDate date];
    picker.maximumDate = [now dateByAddingTimeInterval:604800];
    [picker setDate:now animated:YES];
    self.counter = [now description];
    self.now = [NSDate date];
    self.counter = [self.formatter stringFromDate:self.now];}

这是我的UIImagePickerController的viewController代码,我需要正确显示timerLabel并倒计时:

  - (IBAction)startCamera:(id)sender {
    if (self.image == nil &&  [self.videoFilePath length] == 0) {
        self.imagePickerController = [[UIImagePickerController alloc] init];
        self.imagePickerController.delegate = self;
        self.imagePickerController.allowsEditing = NO;
        self.imagePickerController.videoMaximumDuration = 10;
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            self.imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
        }
        else {
            self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        }
        self.imagePickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:self.imagePickerController.sourceType];
        [self presentViewController:self.imagePickerController animated:NO completion:nil];}
    [[NSBundle mainBundle] loadNibNamed:@"OverlayView" owner:self options:nil];
    self.overlayView.frame = CGRectMake(160,8,0,0);
    self.imagePickerController.cameraOverlayView = self.overlayView;
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *deadline = [NSString stringWithFormat:@"%@/deadline.txt",
                          documentsDirectory];
    NSString *flashName = [NSString stringWithFormat:@"%@/flashName.txt",
                           documentsDirectory];
    NSError *fileError;
    titleLabel.text = [NSString stringWithContentsOfFile:flashName
                                                encoding:NSASCIIStringEncoding
                                                   error:&fileError];
    timerLabel.text = [NSString stringWithContentsOfFile:deadline
                                                encoding:NSASCIIStringEncoding
                                                   error:&fileError];
    if(fileError.code == 0){
        NSLog(@"deadline.txt was read successfully with these contents: %@,",
              timerLabel.text);
        NSLog(@"flashName.txt was read successfully with these contents: %@,",
              titleLabel.text);}
    self.startDate = [NSKeyedUnarchiver unarchiveObjectWithFile:deadline];
    [self refreshLabel];
    [NSTimer scheduledTimerWithTimeInterval:1
                                     target:self
                                   selector:@selector(refreshLabel)
                                   userInfo:nil
                                    repeats:YES];
}
-(void)refreshLabel {
    NSDate *todaysDate = [NSDate date];
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSUInteger unitFlags = NSDayCalendarUnit | NSMinuteCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents *dateComparisonComponents = [gregorian components:unitFlags fromDate:todaysDate toDate:self.startDate options:NSWrapCalendarComponents];
    NSInteger days = [dateComparisonComponents day];
    NSInteger hours = [dateComparisonComponents hour];
    NSInteger minutes = [dateComparisonComponents minute];
    NSInteger seconds = [dateComparisonComponents second];
    self.timerLabel.text = [NSString stringWithFormat:@"%ld:%02ld:%02ld:%02ld", (long)days, (long)hours, (long)minutes, (long)seconds];
    if (days == 0 && hours == 0 && minutes == 0 && seconds == 0) {
        [self.timer invalidate];
        NSLog(@"Time's up!");
    }
}

根据我们昨晚的讨论,您不能以这种方式使用日期格式化程序,因为您正在查看未来的时间,例如 1 天 2 小时 5 分钟,而不是日期。执行此操作的一种方法是将选取器的选定日期传递给图像选取器控制器,并执行与在第一个控制器中执行的几乎相同的操作来获取日期组件。因此,在第一个控制器中,将选取器日期保存到文件而不是字符串:

-(IBAction)refreshLabel; {
    NSDate *selected = [NSDate dateWithTimeIntervalSince1970:[picker.date timeIntervalSince1970] - 1];
    self.counter = [self.formatter stringFromDate:selected];
    NSLog(@"selected is: %@", selected);
    NSDate *todaysDate = [NSDate date];
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSUInteger unitFlags = NSDayCalendarUnit | NSMinuteCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit;
    dateComparisonComponents = [gregorian components:unitFlags fromDate:todaysDate toDate:selected options:NSWrapCalendarComponents];
    NSInteger days = [dateComparisonComponents day];
    NSInteger hours = [dateComparisonComponents hour];
    NSInteger minutes = [dateComparisonComponents minute];
    NSInteger seconds = [dateComparisonComponents second];
    self.counter = [NSString stringWithFormat:@"%ld:%02ld:%02ld:%02ld", (long)days, (long)hours, (long)minutes, (long)seconds];
    self.textField.text = self.counter;
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *deadline = [NSString stringWithFormat:@"%@/deadline.txt", documentsDirectory];
    NSInteger success = [NSKeyedArchiver archiveRootObject:selected toFile:deadline];
    NSLog(@"success is: %d",success);
}

然后在图像选择器控制器中(我只显示计时器标签所需的代码):

- (IBAction)startCamera:(id)sender {
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *deadline = [NSString stringWithFormat:@"%@/deadline.txt", documentsDirectory];
    NSError *fileError;
    self.startDate = [NSKeyedUnarchiver unarchiveObjectWithFile:deadline];
    [self refreshLabel];
    if(fileError.code == 0){
        NSLog(@"deadline.txt was read successfully with these contents: %@,", self.timerLabel.text);
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshLabel) userInfo:nil repeats:YES];
    }
}

-(void)refreshLabel{
    NSDate *todaysDate = [NSDate date];
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSUInteger unitFlags = NSDayCalendarUnit | NSMinuteCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents *dateComparisonComponents = [gregorian components:unitFlags fromDate:todaysDate toDate:self.startDate options:NSWrapCalendarComponents];
    NSInteger days = [dateComparisonComponents day];
    NSInteger hours = [dateComparisonComponents hour];
    NSInteger minutes = [dateComparisonComponents minute];
    NSInteger seconds = [dateComparisonComponents second];
    self.timerLabel.text = [NSString stringWithFormat:@"%ld:%02ld:%02ld:%02ld", (long)days, (long)hours, (long)minutes, (long)seconds];
    if (days == 0 && hours == 0 && minutes == 0 && seconds == 0) {
        [self.timer invalidate];
        NSLog(@"Time's up!");
    }
}

最新更新