Objective-C自定义计时器类应该在模型还是控制器中

时间:2013-08-17 17:56:37

标签: ios objective-c design-patterns model-view-controller nstimer

我创建了一个带有公共API的自定义Timer类,允许访问属性timeLeft,并允许调用类启动和暂停计时器,以及布尔值isTimerPaused。

我需要初始化和启动Timer,并在我的游戏循环内暂停以适应各种情况。所以我一直在我的游戏(模型)中初始化我的计时器:

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

以下是我的Timer API:

@interface Timer : NSObject

-(id)initWithTimerDurationInSeconds:(NSTimeInterval)duration;

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


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

@end

和我的Timer实现

#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,但这似乎效率低下且容易出现稍微不准确的情况。

谢谢!

1 个答案:

答案 0 :(得分:0)

  

使用模型中的计时器,如何连续刷新UI元素?

将计时器移出模型。严重。

您将遇到的MVC的每个图形表示在View图层和Model图层之间都有一个很好的实线,这是有原因的。如果模型对视图了解太多,那么您的应用程序将变得过度数据驱动并变得臃肿。反过来也是如此。将计时器插入控制器,并从控制器将更新路由到模型,以防止任何责任泄漏到应用程序的错误部分。