尝试使用 NSTimer

发布于 2024-12-08 10:42:04 字数 4724 浏览 0 评论 0原文

我在让 NSTimer 工作时遇到问题,可能是因为我不知道如何正确使用它(我尝试阅读苹果文档,但它对我没有多大帮助)。我从 UIDatePicker 获得了一个休息时间,我希望应用程序在到达该时间时调用该方法。很简单,不是吗?所以我的代码如下:

-(IBAction)SetButtonPress:(id)sender{
     NSDate *date = [Picker date];
     alarmTimer = [[AlarmTimer alloc] init];
    [alarmTimer runTimer: Picker.date];
}

现在有些事情遵循标准,但它仍然不起作用。它仍然给我提前 6 小时的时间,当它到达那个时间时,它什么也没做。

我的alarmTimer 类的RunTimer 方法的代码如下:

-(void)RunTimer: (NSDate *) date
{
NSRunLoop *theLoop = [NSRunLoop currentLoop];
[theLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[timer initWithFireDate:date interval:0 target:self selector:@selector(Play) userInfo: nil repeats:NO];
}

现在有一些事情遵循标准,但它仍然不起作用。它仍然给我提前 6 小时的时间,当它到达那个时间时,它什么也没做。

为了以防万一它有帮助,这里是视图控制器的 .h 和 .m 文件: .h:

//
//  Assignment_1ViewController.h
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AlarmTimer.h"

@interface Assignment_1ViewController : UIViewController {
    UIButton *SetButton;
    UIDatePicker *Picker;
    UIButton *CancelButton;
    NSString *time;
    AlarmTimer *alarmTimer;
}

@property (nonatomic, retain) IBOutlet UIButton *SetButton;
@property (nonatomic, retain) IBOutlet UIDatePicker *Picker;
@property (nonatomic, retain) IBOutlet UIButton *CancelButton;

- (IBAction)SetButtonPress:(id)sender;
- (IBAction)CancelButtonPress:(id)sender;
@end

.m:

//
//  Assignment_1ViewController.m
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "Assignment_1ViewController.h"
#import "AlarmTimer.h"

@implementation Assignment_1ViewController
@synthesize Picker;
@synthesize CancelButton;
@synthesize SetButton;

- (void)dealloc
{
    [SetButton release];
    [Picker release];
    [CancelButton release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
}


- (void)viewDidUnload
{
    [self setSetButton:nil];
    [self setPicker:nil];
    [self setCancelButton:nil];
    [super viewDidUnload];
    [alarmTimer release];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (IBAction)SetButtonPress:(id)sender {
    NSDateFormatter *ndf = [[NSDateFormatter alloc] init];

    time = [ndf stringFromDate:self.Picker.date];

    alarmTimer = [AlarmTimer alloc];
    [alarmTimer init];

    NSLog(@"Date is: %@", [ndf dateFromString:time]);

    [alarmTimer RunTimer:[ndf dateFromString:time]];
}

- (IBAction)CancelButtonPress:(id)sender {
}
@end

AlarmTimer 类的代码:

.h:
//
//  Timer.h
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface AlarmTimer : NSObject {
    NSString *time;
    NSTimer *timer;
    AVAudioPlayer *player;
}

-(void) RunTimer: (NSDate *)date;
-(void)Play;
-(void)CancelTimer;

@end

最后,.m:

//
//  Timer.m
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "AlarmTimer.h"
@implementation AlarmTimer

-(id) init
{
    if(self == [super init])
    {
        timer = [NSTimer alloc];
        NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/Time.mp3", [[NSBundle mainBundle] resourcePath]]];
        NSError *error;
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    }
    return self;
}

- (void) RunTimer: (NSDate *)date
{
    [timer initWithFireDate:date interval:86400 target:self selector:@selector(Play) userInfo:nil repeats:NO];
    NSLog(@"Date is: %@", date);
}

-(void) Play
{
    [player play];
    UIAlertView *aView = [[UIAlertView alloc] initWithTitle:@"Holy Chimes!" message:@"If you didn't hear that..." delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
    [aView show];
}

-(void)CancelTimer
{
    time = nil;
}

@end

非常感谢任何可以提供帮助的人!

I'm having a problem getting an NSTimer to work, probably because I don't know how to properly use it (I've tried reading the apple documentation, it didn't help me much). I get a time off of a UIDatePicker and I want the app to call the method when that time is reached. Simple, no? So the code I have is below:

-(IBAction)SetButtonPress:(id)sender{
     NSDate *date = [Picker date];
     alarmTimer = [[AlarmTimer alloc] init];
    [alarmTimer runTimer: Picker.date];
}

A few things now follow standards, but it still doesn't work. It still gives me a time 6 hours ahead, and when it hits that time, it doesn't do anything.

And the code for the RunTimer method of my alarmTimer class is as follows:

-(void)RunTimer: (NSDate *) date
{
NSRunLoop *theLoop = [NSRunLoop currentLoop];
[theLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[timer initWithFireDate:date interval:0 target:self selector:@selector(Play) userInfo: nil repeats:NO];
}

A few things now follow standards, but it still doesn't work. It still gives me a time 6 hours ahead, and when it hits that time, it doesn't do anything.

And just in case it helps, here is the .h and .m files for the view controller:
.h:

//
//  Assignment_1ViewController.h
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AlarmTimer.h"

@interface Assignment_1ViewController : UIViewController {
    UIButton *SetButton;
    UIDatePicker *Picker;
    UIButton *CancelButton;
    NSString *time;
    AlarmTimer *alarmTimer;
}

@property (nonatomic, retain) IBOutlet UIButton *SetButton;
@property (nonatomic, retain) IBOutlet UIDatePicker *Picker;
@property (nonatomic, retain) IBOutlet UIButton *CancelButton;

- (IBAction)SetButtonPress:(id)sender;
- (IBAction)CancelButtonPress:(id)sender;
@end

.m:

//
//  Assignment_1ViewController.m
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "Assignment_1ViewController.h"
#import "AlarmTimer.h"

@implementation Assignment_1ViewController
@synthesize Picker;
@synthesize CancelButton;
@synthesize SetButton;

- (void)dealloc
{
    [SetButton release];
    [Picker release];
    [CancelButton release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
}


- (void)viewDidUnload
{
    [self setSetButton:nil];
    [self setPicker:nil];
    [self setCancelButton:nil];
    [super viewDidUnload];
    [alarmTimer release];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (IBAction)SetButtonPress:(id)sender {
    NSDateFormatter *ndf = [[NSDateFormatter alloc] init];

    time = [ndf stringFromDate:self.Picker.date];

    alarmTimer = [AlarmTimer alloc];
    [alarmTimer init];

    NSLog(@"Date is: %@", [ndf dateFromString:time]);

    [alarmTimer RunTimer:[ndf dateFromString:time]];
}

- (IBAction)CancelButtonPress:(id)sender {
}
@end

And the code for the AlarmTimer class:

.h:
//
//  Timer.h
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface AlarmTimer : NSObject {
    NSString *time;
    NSTimer *timer;
    AVAudioPlayer *player;
}

-(void) RunTimer: (NSDate *)date;
-(void)Play;
-(void)CancelTimer;

@end

And finally, the .m:

//
//  Timer.m
//  Assignment 1
//
//  Created by Jack Schaible on 11-09-28.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "AlarmTimer.h"
@implementation AlarmTimer

-(id) init
{
    if(self == [super init])
    {
        timer = [NSTimer alloc];
        NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/Time.mp3", [[NSBundle mainBundle] resourcePath]]];
        NSError *error;
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    }
    return self;
}

- (void) RunTimer: (NSDate *)date
{
    [timer initWithFireDate:date interval:86400 target:self selector:@selector(Play) userInfo:nil repeats:NO];
    NSLog(@"Date is: %@", date);
}

-(void) Play
{
    [player play];
    UIAlertView *aView = [[UIAlertView alloc] initWithTitle:@"Holy Chimes!" message:@"If you didn't hear that..." delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
    [aView show];
}

-(void)CancelTimer
{
    time = nil;
}

@end

Thanks a lot to anyone who can help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神魇的王 2024-12-15 10:42:04

为什么使用 NSDateFormatter?尝试这样做:

alarmTimer = [AlarmTimer alloc];
[alarmTimer init];

NSLog(@"Date is: %@", self.Picker.date);

[alarmTimer RunTimer: self.Picker.date];

Why do you use NSDateFormatter? try to do it like that:

alarmTimer = [AlarmTimer alloc];
[alarmTimer init];

NSLog(@"Date is: %@", self.Picker.date);

[alarmTimer RunTimer: self.Picker.date];
撑一把青伞 2024-12-15 10:42:04
  1. 通常,+alloc 和 -init 一起执行:Foo *someFoo = [[Foo alloc] init];。不要像使用 timeralarmTimer 变量那样分隔调用。原因是有时初始化器会返回一个与从 +alloc 获得的指针不同的指针,当发生这种情况时,您需要确保存储该新指针。我不知道 NSTimer 是否这样做过,但如果是这样,您当前的代码就会遇到各种麻烦。

  2. 不要尝试重复使用计时器。一旦它触发,就释放它并在需要时创建一个新的。

  3. -SetButtonPress: 中到底有什么疯狂之处?您从日期选择器中获取日期,将其转换为字符串,然后立即将该字符串转换回日期...为什么?

  4. 您使用的计时器间隔为 24 小时(86400 秒)。您是否有一种错误的印象,认为间隔较长的计时器会唤醒后台的应用程序? NSTimer 依赖于运行循环;当运行循环未运行时,计时器不工作。

  5. 如果您坚持通常的 Objective-C 约定并以小写字符开头的命名方法,即 -runTimer: 而不是 ,那么帮助您会更容易-运行定时器:。同样的规则也适用于实例变量。

  1. As a rule, do the +alloc and -init together: Foo *someFoo = [[Foo alloc] init];. Don't separate the calls as you've done with your timer and alarmTimer variables. The reason for this is that sometimes the initializer will return a different pointer than what you get from +alloc, and when that happens you want to be certain to store that new pointer. I don't know if NSTimer ever does that, but if so you'll have all kinds of trouble with your current code.

  2. Don't try to reuse a timer. Once it fires, release it and create a new one when you need to.

  3. What's all that craziness in -SetButtonPress:? You get a date from a date picker, convert it to a string, and then immediately convert that string back to a date... why?

  4. You're using an interval of 24 hours (86400 seconds) for your timer. Are you under the mistaken impression that a timer with a long interval will wake up an app that's in the background? NSTimer relies on the run loop; when the run loop isn't running, the timer isn't working.

  5. It'd be somewhat easier to help you if you'd stick to the usual Objective-C convention and name methods starting with lower-case characters, i.e. -runTimer: instead of -RunTimer:. The same rule applies to instance variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文