2011-05-22 83 views
0

编辑:从我的代码中添加NSRunLoop,如下面的Deepak所述。这是最初在我的代码中,忘记添加,因为它已被注释掉。设置从另一个类的计时器在另一个视图中触发

我有2个类: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设置为,然后将控件传回MainViewController的“原始”实例(当我关闭MVC时)。在这一点上,MainViewController的“新”实例可能只是一个悬挂指针,并且不会再被引用,因此没有段错误。

2)doAlarm:引用self.view,这是应该是MainViewController.view,但因为它在ConfigViewController的示波器的实例,报警图像将永远不会看到反正...

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

上面提到的任何光线都会被粉碎。

非常感谢!

swisscheese。

回答

0

如果您转到initWithFireDate:interval:target:selector:userinfo:repeats:的文档,您会注意到,在定时器初始化时,它尚未安排。您需要添加一个NSRunLoop才能使其正常工作。在如上所述初始化警报之后执行此操作。您可以考虑使用scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:这可以帮您。

这里当然很少有其他的东西。

新MainViewController对象

你猜对。你正在创建一个不相关的对象,只会泄漏。要解决这个问题,您可以保留对MainViewController对象的弱引用。如果你需要在这里重复的计时器

#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 

定时器

我不知道:

@class MainViewController; // Forward declaration 

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

ConfigViewController.m - 你可以这样做如下。有一个替代方案 - performSelector:withObject:afterDelay:。这将在所需延迟后调用对象的方法。做它自己的称呼。这将是这样的 -

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

doAlarm:

我没有得到你是什么,你想在这里知道,但正确的。 self是对MainViewController对象的引用。除非你保留了你以模态方式显示的视图控制器,否则它将被解散和释放。

+0

谢谢Deepak - 我确实注意到initWithFireDate需要将定时器添加到RunLoop中。我相应地编辑了我的代码。通过弱引用,我应该实例化一个MainViewController的“全局”实例(如重复的实例),@property it_weak,然后用新实例替换所有对self的引用?我确信我在这里忽略了OOP的一些基本原则,因为我似乎正在通过跨级消息来限制我的知识。也许我应该只用一种新的闹钟方法,然后看看我是否能到达那里。再次感谢! – swisscheese 2011-05-22 16:20:21

+0

我已在相应部分的答案中添加了关于“MainViewController”的含义。 – 2011-05-22 16:41:09

+0

谢谢迪帕克 - 仍然没有任何运气,它只是默默拒绝执行该方法。我试图在本地方法中代理调用,并且我可以确认可以使用Timer/RunLoop设置调用代理方法。从这个代理方法,以及一个NSLog记录我在方法中,我也尝试[mvcReference doAlarm],但不幸的是没有任何反应 - 我会继续挖掘,但我想我可能不得不重新设计我的整个应用程序基于此问题。谢谢你的帮助。 – swisscheese 2011-05-22 17:40:37

相关问题