mAc
mAc

Reputation: 2514

UILocalNotification is Not invoking at correct time

EDITED :-

Sorry for reediting the Question but actually i am not getting the answer, what i need. I think my way of asking the Question was wrong, so re writing the whole Question :

I have made and App in which is an Customized Alarm App. The UILocalNotification should Invoke at the time selected by me in DatePicker, but is is not invoking at correct timing. For Example, i selected the time as 2:00PM for the Alarm, so the Notification will Invoke between 2:00PM and 2:01PM... but not sure when... it is Giving me a delay of random time. In my TableView you can see that it is the description displayed is also comes Wrong. I know i am from India so it showing GMT timings, but can it could be corrected?

Here is ma Whole Code:-

-----------------------------AppDelegate.m File :------------------------------

@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;
}

-----------------------------mainViewController.m File :------------------------------

@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");
    }
}

This Pic Shows My App View :- Alarm App View

This method is not invoking enter image description here

Upvotes: 0

Views: 891

Answers (3)

sean woodward
sean woodward

Reputation: 1783

I think the problem here has to do with the NSDatePicker returning the seconds of the current time along with the selected time. You need to strip the seconds from the date returned by the NSDatePicker and use that for your alarm and local notification.

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

You should get much better accuracy on your notifications, but I don't think they're guaranteed to be exactly on the split second.

Upvotes: 2

jrturton
jrturton

Reputation: 119292

If you just call description on an NSDate object (which is what you are doing in your cellForRowAtIndexPath method) you will get the internal representation of the date, which is in GMT. You need to use an NSDateFormatter with its locale set to the device locale and use it's stringFromDate: method to obtain dates for display.

Upvotes: 1

Hot Licks
Hot Licks

Reputation: 47759

This is a problem:

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

You're leaking the NSDate you alloc and then throw away. Get rid of the alloc/init and just assign nil to the pointer. But that doesn't explain your larger problem.

Beyond that, either there's something you're not showing us or the date picker is still moving when you sample it.

Upvotes: 1

Related Questions