2013-09-10 2 views
0

У меня есть UIDatePicker на одном viewController, который позволяет пользователю установить дату календаря, час и минуту в форме (солнце 22 июля, 2:33 вечера) для таймера, который будет использоваться в отдельном viewController. На отдельном viewController я пытаюсь отобразить таймер в оверлее на UIImagePickerController в виде «dd: hh: mm: ss» слева от текущего NSDate (сегодняшняя дата/время) и дата datePicker. В основном это таймер обратного отсчета, который начинает отсчет дней, часов, минут, секунд от выбранной даты выбора, когда камера загружается. Моя проблема заключается в том, что, как только камера загружается, таймер отображает правильное оставшееся время в правильном формате, но затем быстро исчезает, когда он попадает в мой метод refreshLabel. Я запустил значения для моего timerLabel, и он корректно отображается в журнале, но как только цикл запускается, когда он возвращает Null для всего. Вчера вечером у меня была какая-то помощь в определении того, что моя проблема, скорее всего, будет связана с форматированием даты из строки, но я не вижу, что это может быть неправильно, поскольку правильная дата изначально отображается, когда камера сначала загружается. Так вот мой код из моего первого ViewController с Datepicker, который устанавливает время timerLabels:Проблемы с NSTimer и NSDateFormatter. Мой таймерLabel исчезает после обновления?

- (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];} 

А вот мой ViewController код UIImagePickerController, что мне нужно иметь 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

В соответствии с нашим обсуждением прошлой ночью, вы не можете использовать формат даты таким образом, потому что вы смотрите в будущее, как 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!"); 
    } 
} 
+0

Я получаю то, что вы говорите о неправильном форматировании для календарной даты, а не в течение нескольких дней, я думал о том, что все это неправильно. Теперь, когда я запускаю приложение после внесения изменений, я получаю эту ошибку: *** Завершение приложения из-за неотображенного исключения «NSInvalidArgumentException», причина: «*** - [NSKeyedUnarchiver initForReadingWithData:]: непонятный архив (0x31, 0x3a , 0x32, 0x33, 0x3a, 0x35, 0x39, 0x3a). Линия, которая бросает это: self.startDate = [NSKeyedUnarchiver unarchiveObjectWithFile: крайний срок]; Это тоже ошибка форматирования? –

+0

@JaredGross, он отлично работает, когда я тестировал его. У вас есть те же строки, что и в методе refreshLabel в первом контроллере? Является ли запись успеха успешной? – rdelmar

+0

Я удалил строку для 'self.textField.text = self.counter;', потому что она меняла текстовое поле на моем первом контроллере, чтобы отобразить время, когда ему нужно прочитать ввод пользователя для titleLabel и сохранить это вместо. Все правильно регистрируется, но все же, я снова в растерянности. –

Смежные вопросы