将Timer从另一个类设置为在另一个视图中触发

时间:2011-05-22 14:38:18

标签: iphone objective-c nstimer

编辑:从我的代码中添加了NSRunLoop,如下面的Deepak所述。这最初是在我的代码中,忘了添加,因为它被注释掉了。

我有两个类:MainViewController和ConfigViewController。用户切换到ConfigView并使用UIDatePicker / UIButton组合来设置日期/时间。从UIDatePicker对象中获取正确的时间后,我按照以下代码设置了NSTimer:

ConfigViewController.m

-(IBAction)setAlarmDate:(id)sender {
//Instantiate to get access to doAlarm:
MainViewController *mvc = [[MainViewController alloc] init];

dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
[dateFormat setTimeStyle:NSDateFormatterShortStyle];
NSString *target = [NSString stringWithFormat:@"%@",[dateFormat stringFromDate:datePicker.date]];

alarmDate = [datePicker date];

mvc.fireTimer = [[NSTimer alloc] 
                  initWithFireDate:alarmDate interval:1 target:mvc
                  selector:@selector(doAlarm:) userInfo:nil repeats:YES];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:mvc.timer forMode:NSDefaultRunLoopMode];


[self dismissModalViewControllerAnimated:NO];
}

doAlarm:方法如下:

MainViewController.m

- (void)doAlarm:(NSTimer *)timer {

NSLog(@"Called doAlarm:");

UIImage *ac = [UIImage imageNamed:@"alarmclock.png"];
[self.alarmview setImage:ac];
[self.alarmview setHidden:NO];
[self.view addSubview:alarmview];
[self.view bringSubviewToFront:alarmview];

}

但是,当我设置闹钟日期时,计时器无法触发。我认为以下问题正在发生:

1)我正在实例化一个MainViewController类的新实例,设置Timer继续,然后当我解除MVC时将控制权传递回MainViewController的“原始”实例。在这一点上,MainViewController的“新”实例可能只是一个悬空指针,并且永远不会再次引用,因此没有段错误。

2)doAlarm:引用self.view,假设是MainViewController.view,但是当它在ConfigViewController范围内实例化时,无论如何都不会看到报警图像......

我想我的理论有点没有根据,但凭借我目前的知识水平,他们对我有意义。

你可以在上面拍摄的任何光都会粉碎。

非常感谢!

swisscheese。

1 个答案:

答案 0 :(得分:0)

如果您转到initWithFireDate:interval:target:selector:userinfo:repeats:的文档,您会注意到计时器初始化时尚未安排。您需要添加NSRunLoop才能使其正常工作。在如上所述初始化警报后执行此操作。

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

您还可以考虑使用scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:为您做到这一点。

这里当然没有其他的东西。

新的MainViewController对象

你猜对了。您正在创建一个只会泄漏的无关对象。要解决此问题,您可以维护对MainViewController对象的弱引用。您可以按照以下方式执行此操作 -

@class MainViewController; // Forward declaration 

@interface ConfigViewController {
    ...
    MainViewController *mainViewController;
}
...
@property (nonatomic, assign) MainViewController *mainViewController;
...
@end
ConfigViewController.m中的

#import "MainViewController.h"

@implementation ConfigViewController

@synthesize mainViewController;
...

- (IBAction)setAlarmDate:(id)sender {
    dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateStyle:NSDateFormatterMediumStyle];
    [dateFormat setTimeStyle:NSDateFormatterShortStyle];

    alarmDate = [datePicker date];

    mainViewController.fireTimer = [[NSTimer alloc] 
                  initWithFireDate:alarmDate interval:1 target:mainViewController
                  selector:@selector(doAlarm:) userInfo:nil repeats:YES];

    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:mainViewController.timer forMode:NSDefaultRunLoopMode];

    mainViewController = nil;
    [self dismissModalViewControllerAnimated:NO];
}
...
@end

<强>定时器

我不确定你是否需要重复计时器。还有另一种选择 - performSelector:withObject:afterDelay:。这将在对象上调用一个方法,该方法在所需的延迟之后调用。它本身就是什么。它会是这样的 -

[mvcReference performSelector:@selector(doAlarm) 
                   withObject:nil 
                   afterDelay:[datePicker.date timeIntervalSinceNow]];

<强> doAlarm:

我没有得到你想知道的,但你是对的。 self是对MainViewController对象的引用。除非您保留以模态方式显示的视图控制器,否则它将被解除并取消分配。