2010-07-10 3 views
3

Так что я пытаюсь настроить основной таймер, но я терплю неудачу. В основном все, что я хочу, - запустить 60-секундный таймер, когда пользователь нажимает кнопку, и обновлять метку с оставшимся временем (например, обратным отсчетом). Я создал свой лейбл и кнопку и связал их в IB. Затем я создал IBAction для кнопки. Теперь, когда я попытался обновить метку на основе таймера, мое приложение закручивается. Вот мой код:Проблема NSTimer

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 1 
         target: self 
         selector:@selector(updateLabelDisplay) 
         userInfo: nil repeats:YES]; 

У меня также есть функция updateLabelDisplay, которая определяет, сколько раз таймер побежал, а затем вычесть это число из 60 и отображает это число в метке обратного отсчета. Может ли кто-нибудь сказать мне, что я делаю неправильно?

+0

Можете ли вы рассказать о том, «мое приложение прикручивает?». Что вы можете наблюдать? –

+0

Также, на основе вашего описания, похоже, что у вас есть нижняя граница (обратный отсчет от 60), поэтому, предположительно, вы захотите в какой-то момент сделать недействительным таймер. Хотя это не ваша проблема, вы захотите позже ссылаться на таймер, чтобы сделать ее недействительной. Возможно, вы делаете это позже в своем коде, но так как вы использовали локальный var вначале, я решил, что стоит упомянуть, чтобы потом немного поправить головную боль. –

+0

В основном этикетка не обновляется. – Roosh

ответ

11

Хорошо, хорошо для начала, проверить это, если вы еще не: Official Apple Docs about Using Timers

На основании вашего описания, вы, вероятно, хотите, код, который выглядит примерно так. Я сделал некоторые предположения относительно поведения, но вы можете по вкусу.

В этом примере предполагается, что вы хотите сохранить ссылку на таймер, чтобы можно было приостановить его или что-то в этом роде. Если это не так, вы можете изменить метод handleTimerTick, чтобы он принимал NSTimer * в качестве аргумента и использовал это для отмены действия таймера по истечении срока его действия.

@interface MyController : UIViewController 
{ 
    UILabel * theLabel; 

    @private 
    NSTimer * countdownTimer; 
    NSUInteger remainingTicks; 
} 

@property (nonatomic, retain) IBOutlet UILabel * theLabel; 

-(IBAction)doCountdown: (id)sender; 

-(void)handleTimerTick; 

-(void)updateLabel; 

@end 

@implementation MyController 
@synthesize theLabel; 

// { your own lifecycle code here.... } 

-(IBAction)doCountdown: (id)sender 
{ 
    if (countdownTimer) 
    return; 


    remainingTicks = 60; 
    [self updateLabel]; 

    countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: @selector(handleTimerTick) userInfo: nil repeats: YES]; 
} 

-(void)handleTimerTick 
{ 
    remainingTicks--; 
    [self updateLabel]; 

    if (remainingTicks <= 0) { 
    [countdownTimer invalidate]; 
    countdownTimer = nil; 
    } 
} 

-(void)updateLabel 
{ 
    theLabel.text = [[NSNumber numberWithUnsignedInt: remainingTicks] stringValue]; 
} 


@end 
+3

Стоит отметить, что еще лучший способ сделать это - использовать временной интервал для обновления метки на основе прошедшего времени вместо того, чтобы полагаться на счетчик тиков. Из-за характера runloops вам не гарантируется какая-либо точность в том, когда срабатывает таймер. Но вышеприведенный пример достаточно хорош для примера кода. –

+0

Большое вам спасибо! Только один вопрос, doCountdown будет связан с моим UIButton правильно? – Roosh

+0

Это правильно. doCountdown: это действие для подключения к вашей кнопке. –

1

Это может быть немного поздно, чтобы отправить второй ответ на этот вопрос, но я искал хорошее место, чтобы опубликовать свое собственное решение этой проблемы. В случае, если это полезно для всех здесь. Он срабатывает 8 раз, но, конечно, это может быть настроено по вашему усмотрению. Таймер освобождает себя от времени.

Мне нравится этот подход, потому что он поддерживает счетчик, интегрированный с таймером.

Чтобы создать что-то экземпляр вызова, как:

SpecialKTimer *timer = [[SpecialKTimer alloc] initWithTimeInterval:0.1 
                 andTarget:myObject 
                 andSelector:@selector(methodInMyObjectForTimer)]; 

Во всяком случае, вот файлы заголовков и метод.

//Header 

#import <Foundation/Foundation.h> 

@interface SpecialKTimer : NSObject { 

    @private 

    NSTimer *timer; 

    id target; 
    SEL selector; 

    unsigned int counter; 

} 

- (id)initWithTimeInterval:(NSTimeInterval)seconds 
       andTarget:(id)t 
       andSelector:(SEL)s; 
- (void)dealloc; 

@end 

//Implementation 

#import "SpecialKTimer.h" 

@interface SpecialKTimer() 

- (void)resetCounter; 
- (void)incrementCounter; 
- (void)targetMethod; 

@end 

@implementation SpecialKTimer 

- (id)initWithTimeInterval:(NSTimeInterval)seconds 
       andTarget:(id)t 
       andSelector:(SEL)s { 

    if (self == [super init]) { 

     [self resetCounter]; 

     target = t; 
     selector = s; 

     timer = [NSTimer scheduledTimerWithTimeInterval:seconds 
               target:self 
               selector:@selector(targetMethod) 
               userInfo:nil 
               repeats:YES]; 

    } 

    return self; 

} 

- (void)resetCounter { 

    counter = 0; 

} 

- (void)incrementCounter { 

    counter++; 

} 

- (void)targetMethod { 

    if (counter < 8) { 

     IMP methodPointer = [target methodForSelector:selector]; 
     methodPointer(target, selector); 

     [self incrementCounter]; 

    } 

    else { 

     [timer invalidate]; 
     [self release]; 

    } 

} 

- (void)dealloc { 

    [super dealloc]; 

} 

@end 
+0

Вызов '-dealloc' на себя плохой. См. Http://stackoverflow.com/questions/3819603/suicide-objective-c-objects-calling-their-own-dealloc-methods-on-themselves. – SK9