UILocalNotification 没有在正确的时间调用

Posted

技术标签:

【中文标题】UILocalNotification 没有在正确的时间调用【英文标题】:UILocalNotification is Not invoking at correct time 【发布时间】:2011-11-04 10:55:49 【问题描述】:

已编辑:-

很抱歉重新编辑问题,但实际上我没有得到答案,我需要什么。我认为我提出问题的方式是错误的,所以重新编写整个问题:

我已经制作了一个应用程序,其中是一个定制的警报应用程序。 UILocalNotification 应该在我在 DatePicker 中选择的时间调用,但不是在正确的时间调用。 例如,我为闹钟选择了时间为下午 2:00,因此通知将在下午 2:00 到下午 2:01 之间调用……但不确定何时……它给了我随机时间的延迟。 在我的 TableView 中你可以看到显示的描述也是错误的。我知道我来自印度,所以它显示的是 GMT 时间,但可以更正吗?

这是完整的代码:-

------------------AppDelegate.m 文件:------ ------------------------------------

@synthesize window,viewController,timeViewController;

NSString *kRemindMeNotificationDataKey = @"kRemindMeNotificationDataKey";

#pragma mark -
#pragma mark === Application Delegate Methods ===
#pragma mark -

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions     


    int x = [[NSUserDefaults standardUserDefaults] integerForKey:@"Mayank"];
    if( x == 1 )
    
        timeViewController = [[TimeViewController alloc]initWithNibName:@"TimeViewController" bundle:nil];
        timeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

        CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
        CGRect frame = timeViewController.view.frame;
        frame.origin = CGPointMake(frame.origin.x,frame.origin.y + statusBarFrame.size.height );
        timeViewController.view.frame = frame;

        [self.window addSubview:timeViewController.view];
    
    else
    
        [[NSUserDefaults standardUserDefaults]setInteger:1 forKey:@"Mayank"];
        [[NSUserDefaults standardUserDefaults]synchronize]; 

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Do you want to set the Default Alarm?" message:@"at 4:20 PM" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok",nil];
        [alert show];
        [alert release];
    

    sleep(1);
    [self.window makeKeyAndVisible];

    application.applicationIconBadgeNumber = 0;
    // Handle launching from a notification
    UILocalNotification *localNotification =
    [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotification) 
        NSString *reminderText = [localNotification.userInfo 
                                  objectForKey:kRemindMeNotificationDataKey];
        [viewController showReminder:reminderText];
    

    return YES;

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

    if(buttonIndex == 0)
    
        timeViewController = [[TimeViewController alloc]initWithNibName:@"TimeViewController" bundle:nil];
        timeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;


        CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
        CGRect frame = timeViewController.view.frame;
        frame.origin = CGPointMake(frame.origin.x,frame.origin.y + statusBarFrame.size.height );
        timeViewController.view.frame = frame;


        [self.window addSubview:timeViewController.view];
    
    if(buttonIndex == 1)
    
        viewController = [[SetAlarmViewController alloc]initWithNibName:@"SetAlarmViewController" bundle:nil];
        viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

        CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
        CGRect frame = viewController.view.frame;
        frame.origin = CGPointMake(frame.origin.x,frame.origin.y + statusBarFrame.size.height );
        viewController.view.frame = frame;

        [self.window addSubview:viewController.view];       
    



- (void)application:(UIApplication *)application 
didReceiveLocalNotification:(UILocalNotification *)notification 

    NSString *reminderText = [notification.userInfo
                              objectForKey:kRemindMeNotificationDataKey];
    [viewController showReminder:reminderText];
    application.applicationIconBadgeNumber = 0;

------------------ma​​inViewController.m 文件:------ ------------------------------------

@implementation SetAlarmViewController
@synthesize datePicker,tableview, eventText,titleBar,setAlarmButton,returnKeyType;


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad 

    [super viewDidLoad];

    appDelegate = (The420DudeAppDelegate *)[[UIApplication sharedApplication] delegate];    
    eventText.returnKeyType = UIReturnKeyDone;

//  datePicker.minimumDate = [NSDate date];
    NSDate *now = [NSDate date];
    [datePicker setDate:now animated:YES];
    eventText.delegate = self;
    index = 0;


-(void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:YES];
    [self.tableview reloadData];


- (IBAction) scheduleAlarm:(id) sender 
    [eventText resignFirstResponder];

// Get the current date
    NSDate *pickerDate = [self.datePicker date];

    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
    if (localNotif == nil)
        return;
    localNotif.fireDate = pickerDate;
//  NSLog(@"%@",localNotif.fireDate);
    localNotif.timeZone = [NSTimeZone defaultTimeZone];
//  NSLog(@"%@",localNotif.timeZone);

    // Notification details
    localNotif.alertBody = [eventText text];

    // Set the action button
    localNotif.alertAction = @"Show me";
    localNotif.repeatInterval = NSDayCalendarUnit;
    localNotif.soundName = @"jet.wav";
    // Specify custom data for the notification
    NSDictionary *userDict = [NSDictionary dictionaryWithObject:eventText.text
                                                         forKey:kRemindMeNotificationDataKey];
    localNotif.userInfo = userDict;

    // Schedule the notification
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
    [localNotif release];

    [self.tableview reloadData];
    eventText.text = @"";

    viewController = [[TimeViewController alloc] initWithNibName:@"TimeViewController" bundle:nil];
    [self presentModalViewController:viewController animated:YES];


#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    // Return the number of sections.
    return 1;



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    // Return the number of rows in the section.
    return [[[UIApplication sharedApplication] scheduledLocalNotifications] count];


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    index = indexPath.row;
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Warning!!!" 
                                                        message:@"Are you sure you want to Delete???" delegate:self
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:@"Ok",nil];
    [alertView show];
    [alertView release];


- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

    NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
    UILocalNotification *notify = [notificationArray objectAtIndex:index];

    if(buttonIndex == 0)
    
        // Do Nothing on Tapping Cancel...
    
    if(buttonIndex ==1)
    
        if(notify)
            [[UIApplication sharedApplication] cancelLocalNotification:notify];
    
    [self.tableview reloadData];


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    
    // Configure the cell...

    NSArray *notificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
    UILocalNotification *notif = [notificationArray objectAtIndex:indexPath.row];

    [cell.textLabel setText:notif.alertBody];
    [cell.detailTextLabel setText:[notif.fireDate description]];    
    return cell;



- (void)showReminder:(NSString *)text 
    /*
     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Reminder" 
     message:@"hello" delegate:self
     cancelButtonTitle:@"OK"
     otherButtonTitles:nil];
     [alertView show];
     [self.tableview reloadData];
     [alertView release];
     */

    NSString *path = [[NSBundle mainBundle]pathForResource:@"jet" ofType:@"wav"];
    NSURL *url = [NSURL fileURLWithPath:path];

    player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
    player.numberOfLoops = -1;
    [player play];

    UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:nil];
    [actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
    [actionSheet showInView:self.view];
//  [actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
    [actionSheet release];


- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

    [player stop];
    if(buttonIndex == 0)
    
        NSLog(@"OK Tapped");
    
    if(buttonIndex ==  1)
    
        NSLog(@"Cancel Tapped");
    

这张图片显示了我的应用视图:-

这个方法没有调用

【问题讨论】:

【参考方案1】:

我认为这里的问题与 NSDatePicker 返回当前时间的秒数以及所选时间有关。您需要从 NSDatePicker 返回的日期中删除秒数,并将其用于警报和本地通知。

NSDate *selectedDate = [datePicker date]; // you don't need to alloc-init the variable first
NSCalendar *cal = [NSCalendar currentCalendar];  
NSDateComponents *dc = [cal components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:selectedDate];
selectedDate = [cal dateFromComponents:dc]; // now you have an NSDate with zero seconds for your alarm

您的通知应该会获得更高的准确性,但我认为不能保证它们在瞬间准确。

【讨论】:

【参考方案2】:

这是个问题:

    NSDate *selectedDate = [[NSDate alloc] init];
    selectedDate = [datePicker date];

您正在泄漏您分配的 NSDate,然后将其丢弃。摆脱 alloc/init 并将 nil 分配给指针。但这并不能解释你更大的问题。

除此之外,要么是您没有向我们展示某些东西,要么是在您采样时日期选择器仍在移动。

【讨论】:

嘻嘻...我也阅读了您之前的评论。 :) sry 老兄,实际上我已经写了很多代码,所以我可能也忘记了纠正这个问题。 你还需要什么......我应该粘贴我的整个代码......它只是一个小项目只有一个视图控制器......我只粘贴了主要部分,因为它不应该看到很长否则有一些天才投票否决它.. :( 我怀疑你没有发布整个 scheduleAlarm 方法。否则您发布的消息与该版本的代码不对应。 (抱歉,看起来如此可疑,但我们一直看到这种事情。) 你在印度,对吧?这解释了前两个时间值之间的差异。唯一无法解释的值是 10:10:26 值,这对代码来说甚至不是必需的,因为您之前从 datePicker 获得了日期。我怀疑某种未初始化的变量情况,但我看不到。【参考方案3】:

如果您只是在 NSDate 对象上调用 description(这是您在 cellForRowAtIndexPath 方法中所做的),您将获得日期的内部表示,即 GMT 格式。您需要使用NSDateFormatter 并将其语言环境设置为设备语言环境,并使用它的stringFromDate: 方法来获取显示日期。

【讨论】:

你能给我一些代码或链接或一些提示吗...在我的代码中我正在重新加载表,所以它设置了所有行的修改时间。 :(

以上是关于UILocalNotification 没有在正确的时间调用的主要内容,如果未能解决你的问题,请参考以下文章

UILocalNotification 声音未在设备上播放

UILocalNotification 2 分钟后重复警报

iPhone静音时的UILocalNotification警报

UILocalNotification 不会触发

UIlocalNotification 现在确实在没有启动后台任务的情况下出现

UILocalNotification 显示 400 个徽章