1

我已經創建了一個自定義的計時器類與公共API允許訪問屬性timeLeft,並允許調用類來啓動和暫停計時器,以及布爾isTimerPaused。應該Objective-C自定義計時器類在模型或控制器

我需要將計時器初始化並啓動,並在各種情況下暫停在我的遊戲循環中。

#define timerDuration 10 
    self.timer =[[Timer alloc] initWithTimerDurationInSeconds:timerDuration]; 

下面來看看我的計時器API:所以我有這樣初始化我的定時器在我的遊戲(模型)已先行

@interface Timer : NSObject 

-(id)initWithTimerDurationInSeconds:(NSTimeInterval)duration; 

-(void)startTimer; 
-(void)pauseTimer; 


@property (nonatomic, getter = isTimerPaused)BOOL timerPaused; 
@property (nonatomic)NSTimeInterval timeLeft; 

@end 

和我的定時器實現

#import "Timer.h" 

@interface Timer() 

@property (nonatomic)NSTimeInterval timeRemaining; 
@property (nonatomic)NSTimeInterval duration; 
@property (strong, nonatomic) NSTimer *timer; 
@property (strong, nonatomic)NSDate *targetTime; 

@end 

@implementation Timer 

-(id)initWithTimerDurationInSeconds:(NSTimeInterval)duration 
{ 
    self = [super init]; 

    if (self) 
    { 
     if (duration) _duration = duration; 
     else NSLog(@"Must Initialize Timer With Duration"); 
    } 

    return self; 
} 

-(void)startTimer 
{ 
    self.targetTime = [NSDate dateWithTimeIntervalSinceNow:self.duration]; 
    self.timer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:@selector(updateTimerLabel) userInfo:nil repeats:YES]; 
    self.timerPaused = NO; 

} 
-(void)pauseTimer 
{ 
    self.timerPaused = !self.isTimerPaused; 
    if (self.isTimerPaused) 
    { 
     self.timeRemaining = [self.targetTime timeIntervalSinceNow]; 
     [self.timer invalidate]; 
     self.timer = nil; 
    } 
    else 
    { 
     self.targetTime = [NSDate dateWithTimeIntervalSinceNow:self.timeRemaining]; 
     self.timer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:@selector(updateTimerLabel) userInfo:nil repeats:YES]; 
    } 

} 

-(void)updateTimeLeft 
{ 
    self.timeLeft = [self.targetTime timeIntervalSinceNow]; 

    if (self.timeLeft <=0) 
    { 
     [self.timer invalidate]; 
     ago", -timeLeft]; 
    } 
} 
@end 

這一切理論上都會很好,因爲我可以根據需要在我的遊戲循環中啓動和停止計時器,並且我可以從我的控制器訪問更新計時器UILabel的時間。

我的問題是這樣的,如果計時器在我的控制器中,我可以簡單地更新updateTimeLeft方法中的標籤。隨着模型中的計時器,我該如何持續刷新UI元素。我的想法是在我的控制器中有一些連續的計時器,它會使用計時器的timeLeft屬性更新UILabel,但這似乎效率低下,並且容易出現稍微不準確的情況。

謝謝!

+0

正確的MVC模式的控制器應該只改變模型層和當前視圖的狀態。定時器的最佳位置可能是模型層內的一些服務。 –

+0

感謝您的評論tereško。這是我想到的結論。問題是,我如何最好地更新Controller的相應UI元素? – altyus

+0

取決於您使用的MVC的解釋。在接近古典的東西中,你會看到觀察模型狀態變化的觀點。當定時器在模型層中引起某些變化時,視圖會檢測到這一變化,並從模型層請求數據來說明這種變化。不幸的是,大多數人沒有實現MVC。 –

回答

0

隨着模型中的計時器,我該如何持續刷新UI元素?

將計時器移出模型。認真。

您將遇到的MVC的每個圖形表示在View層和Model層之間都有一條很好的實線,這是有原因的。如果模型太瞭解視圖,那麼您的應用程序會變得過於數據驅動和臃腫。相反的情況也是如此。將定時器插入控制器,並將更新路由到控制器的模型,以防止任何責任泄露到應用程序的錯誤部分。

+0

謝謝CodaFi。您的評論讓我坐在這裏一秒鐘,想一想我爲什麼首先要在我的控制器中使用計時器。當我大聲說出原因時,很明顯我仍然可以用一種簡單而複雜的方式實現所需的功能。這裏的目標是讓我的遊戲循環與計時器並行。現在看起來很愚蠢,但這可以通過聽取控制器中的計時器並在遊戲模型中調用一個方法來實現 - (void)nextQuestion; – altyus

+0

還有一件事要補充。在我的知識中,我必須克服的一個概念性差距才能正確實現我之前使用的代表。我需要將我的Timer類配置爲委託,並在我的視圖控制器中實現委託方法。這樣,我可以在定時器更改或過期時通知視圖控制器,並相應地更新我的UI。基本的iOS MVC,但希望這會幫助像我這樣的新手!乾杯 – altyus

相關問題