【问题标题】:Timer not counting down correctly计时器未正确倒计时
【发布时间】:2013-07-06 00:16:58
【问题描述】:

所以我有一个计时器,可以从用户输入的任务中获取NSTimeInterval。计时器使用 NSDateComponents 类将时间间隔分隔为HH:MM:SS 格式。出于某种原因,每次发送计时器选择器时,我的标签(具有HH:MM:SS 格式)都不会更新。我知道选择器有效,因为每秒都会发送 NSLog 消息,但标签不会更新。任何想法为什么?

TimerViewController.h

@interface DetailViewController : UIViewController{
    NSCalendar *gregorianCalendar;
    NSDateComponents *components;
}
@property (weak, nonatomic) IBOutlet UILabel *timeLeft;
@property (weak, nonatomic) IBOutlet UILabel *timerLabel;
@property (nonatomic, strong) Tasks *testTask;
@property NSTimer *timer;
@property (strong, nonatomic) NSDate *now;
@property (strong, nonatomic) NSDate *date1;
-(void)timerAction:(NSTimer *)t;
@end

TimerViewController.m

 - (void)viewDidLoad
{
    [super viewDidLoad];
    gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
   timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
    [timer fire];
    self.date1 = [NSDate dateWithTimeInterval:[testTask timeInterval] sinceDate:[NSDate date]];
}
-(void)timerAction:(NSTimer *)t{
   NSDateFormatter *timerFormatter = [[NSDateFormatter alloc]init];
    [timerFormatter setDateFormat:@"hh:mm:ss"];
     NSDate *now = [NSDate date];
    components = [gregorianCalendar components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit  fromDate:now toDate:self.date1 options:0];

    NSString *timeRemaining = nil;
    if([now compare:self.date1] == NSOrderedAscending){
        timeRemaining = [NSString stringWithFormat:@"%02d:%02d:%02d", [components hour], [components minute], [components second]];
        NSLog(@"works %@", timeRemaining);
    } else {
        timeRemaining = [NSString stringWithFormat:@"00:00:00"];
        [timer invalidate];
        timer = nil;
        NSLog(@"ended");
    }
   timerLabel.text = timeRemaining;
    [timerLabel setNeedsDisplay];
    [self.view setNeedsDisplay];
}

错误信息:

*** -[__NSCFCalendar components:fromDate:toDate:options:]: toDate cannot be nil
I mean really, what do you think that operation is supposed to mean with a nil toDate?
An exception has been avoided for now.
A few of these errors are going to be reported with this complaint, then further violations will simply silently do whatever random thing results from the nil.
Here is the backtrace where this occurred this time (some frames may be missing due to compiler optimizations):
(
    0   CoreFoundation                      0x015bdc78 -[__NSCFCalendar components:fromDate:toDate:options:] + 200
    1   ToDoTasks                           0x0000980b -[DetailViewController timerAction:] + 299
    2   CoreFoundation                      0x0160bff6 -[__NSCFTimer fire] + 150
    3   ToDoTasks                           0x00009393 -[DetailViewController viewDidLoad] + 435
    4   UIKit                               0x002e11c7 -[UIViewController loadViewIfRequired] + 536
    5   UIKit                               0x002e1232 -[UIViewController view] + 33
    6   UIKit                               0x002e14da -[UIViewController contentScrollView] + 36
    7   UIKit                               0x002f88e5 -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 36
    8   UIKit                               0x002f89cb -[UINavigationController _layoutViewController:] + 43
    9   UIKit                               0x002f8c76 -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 254
    10  UIKit                               0x002f8d71 -[UINavigationController _startTransition:fromViewController:toViewController:] + 72
    11  UIKit                               0x002f989b -[UINavigationController _startDeferredTransitionIfNeeded:] + 386
    12  UIKit                               0x002f9e93 -[UINavigationController pushViewController:transition:forceImmediate:] + 1030
    13  UIKit                               0x002f9a88 -[UINavigationController pushViewController:animated:] + 62
    14  ToDoTasks                           0x00006acf -[ToDoTableViewController tableView:didSelectRowAtIndexPath:] + 1567
    15  UIKit                               0x002af285 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1194
    16  UIKit                               0x002af4ed -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 201
    17  Foundation                          0x00cb95b3 __NSFireDelayedPerform + 380
    18  CoreFoundation                      0x0156d376 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
    19  CoreFoundation                      0x0156ce06 __CFRunLoopDoTimer + 534
    20  CoreFoundation                      0x01554a82 __CFRunLoopRun + 1810
    21  CoreFoundation                      0x01553f44 CFRunLoopRunSpecific + 276
    22  CoreFoundation                      0x01553e1b CFRunLoopRunInMode + 123
    23  GraphicsServices                    0x0260f7e3 GSEventRunModal + 88
    24  GraphicsServices                    0x0260f668 GSEventRun + 104
    25  UIKit                               0x001ffffc UIApplicationMain + 1211
    26  ToDoTasks                           0x00001fad main + 141
    27  ToDoTasks                           0x00001ed5 start + 53
)
2013-07-05 18:00:51.452 ToDoTasks[30968:c07] ended

【问题讨论】:

  • 尝试输出timeRemaining (NSLog(@"timer works %@", timeRemaining);)。我猜你的时差有时不会改变。
  • 哦,你说得对,哈哈。那我该怎么办?

标签: iphone ios objective-c timer nstimer


【解决方案1】:

date1 设为属性并执行

self.date1 = [NSDate dateWithTimeInterval:[testTask timeInterval] sinceDate:now];

viewDidLoad 内。这样你的时差实际上会减少。

从下面编辑:

不要让您的 now 日期成为属性方法,在您第一次编辑时将其放回您的 timerAction

编辑2:

viewDidLoad 中更改您的工作流程。先设置self.date1,然后安排定时器。

【讨论】:

  • 我遇到了最奇怪的错误。听起来 Apple 在嘲笑我 LOL:“-[__NSCFCalendar components:fromDate:toDate:options:]: toDate 不能是 nil 我的意思是真的,你认为这个操作对于 nil toDate 应该意味着什么?一个例外是暂时避免。此投诉将报告其中一些错误,然后进一步的违规行为将简单地默默地执行 nil 导致的任何随机事情。这是这次发生这种情况的回溯(某些帧可能由于以下原因而丢失编译器优化):“
  • 这意味着您的toDatenil。您是否将 date1 设为弱属性?
  • date1 应该是一个强大的属性!
  • no :( 我仍然遇到这些奇怪的错误!(即使我将其更改为 strong)
  • 你能更新你上面的问题,以便我能看到你的新代码吗?
【解决方案2】:

您需要重新绘制视图以更新值

像这样:

    [self.superview setNeedsDisplay];

看看这个:Redrawing a view in ios

所以你的问题是时间间隔没有改变,使用这个:

从哪里开始保存日期:

NSDate *then = [NSDate now];//gives you the current time 

当执行操作时保存下一个日期:

NSDate *now = [NSDate now]; 

然后得到时间间隔:

NSTimeInterval secondsBetween = [now timeIntervalSinceDate:then];

【讨论】:

  • hmm...superview 在我的视图控制器中无效,所以我把这个:[self.view setNeedsDisplay]; 在我的计时器选择器中紧跟在timerLabel.text = timeRemaining; 之后,但仍然没有结果..
  • 尝试做 timerLabel.text = timeRemaining; [timerLabel setNeedsDisplay];然后 [self.view setNeedsDisplay];这行得通吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多