编辑:从我的代码中添加了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。
答案 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
对象的引用。除非您保留以模态方式显示的视图控制器,否则它将被解除并取消分配。