How to make register notification in Objective C? - ios

I have an online radio. The radio has programs at different times, programs are displayed in a list.
My need is that when one tap and hold on the list of program he schedule a notification to the User.
examplo program in list:
Tap and hold is already running (code below):
-(void)registerHour:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint ponto = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:ponto];
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.imageAgendamento.hidden = false;
NSString *test = [ NSString stringWithFormat:#"%#",[[results objectAtIndex:indexPath.row] objectForKey:#"hour" ]];
NSLog(#"hour -> %#", test);
}
}
The test is where has the time of notification "09:00" (in direct
format JSON)
appDelegate.m i add:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
}
Looked at several tutorials and researched in various places, I could not solve my problem any way. What I need to do to get this notification schedule?

You can send a 5 min delayed local notification using the code below:
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
NSDate *currentDate = [NSDate date];
[dateComponents setMinute:5];
NSDate *fireDate = [gregorian dateByAddingComponents:dateComponents toDate:currentDate options:0];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
// Configure the notification
// ....
//
localNotification.fireDate = fireDate;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
But I think what you need to do is using an NSTimer or simply the performSelector:withObject:afterDelay: method of NSObject.

Related

How to fix "exc_bad_instruction (code=exc_i386_invop subcode=0x0)"

I want to make a timer in my app, but i find a problem like this:
My code run very well at viewController which contain the code below, but after i dismiss this viewController a few seconds, Xcode will report an erro: exc_bad_instruction (code=exc_i386_invop subcode=0x0
If i didn't use dispatch_suspend(self.timer) and dispatch_resume(self.timer), everything will be ok
otherwise, I can see the error will happen when Xcode deal with [viewController .cxx_destruct]
so, anyone can tell me how to fix it?
Thank you
Here is my code,
- (void)timeButtonClick:(UIButton *)button{
if (self.isTiming == YES){
self.isTiming = NO;
self.executeTime = [self.timeButton currentTitle];
dispatch_suspend(self.timer);
}else if (self.isTiming == NO){
self.isTiming = YES;
self.createDate = [NSDate date];
dispatch_resume(self.timer);
}
}
- (dispatch_object_t)timer{
if (_timer == nil) {
dispatch_queue_t timerQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, timerQueue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
__weak typeof (self)weakSelf = self;
dispatch_source_set_event_handler(timer, ^{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"HH:mm:ss";
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
NSCalendarUnit unit = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDate *currentDate = [NSDate date];
NSDateComponents *currentCmps = [calendar components:unit fromDate:weakSelf.createDate toDate:currentDate options:NSCalendarWrapComponents];
NSDate *executeTime = [dateFormatter dateFromString:weakSelf.executeTime];
NSDateComponents *executeCmps = [calendar components:unit fromDate:executeTime];
NSString *newExecuteTime = [NSString stringWithFormat:#"%02ld:%02ld:%02ld", executeCmps.hour + currentCmps.hour, executeCmps.minute + currentCmps.minute, executeCmps.second + currentCmps.second];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.timeButton setTitle:newExecuteTime forState:UIControlStateNormal];
});
});
_timer = timer;
}
return _timer;
}
Move your timer to another place like AppDelegate, you are getting this error because you are dispatching the timer to another thread, then when the VC is dismissed the timer wants to set the title to timeButton which wa salready destroyed when the VC was dismissed.
You could also try to make a strong weakself, but I really suggest you to move the timer code to another class.

UILocalNotification getting called repetitively as the app launches

I don't know what is the problem here but everytime I run my app , local notifications get called repetitively showing fireDate as NULL.I am trying to take care of this issue from the past 5hrs now.I need help!!!
"<UIConcreteLocalNotification: 0x7f872ead7630>{fire date = (null), time zone = (null), repeat interval = NSCalendarUnitDay, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Monday, 7 September 2015 5:32:44 pm India Standard Time, user info = (null)}",
I have done enough research on UILocalNotification to get started with it,but i'm still facing this problem.
-(void)setDate:(NSDate*)myfireDate andTime1InString: (NSString*)time1Str andTime2InString:(NSString*)time2Str andTime3InString:(NSString*)time3Str{
//concatenate myFireDate with all three times one by one
NSString *myFireDateInString = [dateFormatter stringFromDate:myfireDate];
myFireDateInString = [myFireDateInString stringByAppendingString:#" "];
NSString *dateWithTime1InString = [myFireDateInString stringByAppendingString:time1Str];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *dateWithTime1 = [dateFormatter dateFromString:dateWithTime1InString];
NSString *mySecondFireDateInString;
NSString *dateWithTime2InString;
NSDate *dateWithTime2;
if ([time2Str length] !=0){
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
mySecondFireDateInString = [dateFormatter stringFromDate:myfireDate];
mySecondFireDateInString = [mySecondFireDateInString stringByAppendingString:#" "];
dateWithTime2InString = [mySecondFireDateInString stringByAppendingString:time2Str];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
dateWithTime2 = [dateFormatter dateFromString:dateWithTime2InString];
}
NSString *myThirdFireDateInString;
NSString *dateWithTime3InString;
NSDate *dateWithTime3;
if ([time3Str length]!=0){
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
myThirdFireDateInString = [dateFormatter stringFromDate:myfireDate];
myThirdFireDateInString = [myThirdFireDateInString stringByAppendingString:#" "];
dateWithTime3InString = [myThirdFireDateInString stringByAppendingString:time3Str];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
dateWithTime3 = [dateFormatter dateFromString:dateWithTime3InString];
}
NSLog(#"%#",dateWithTime3);
NSLog(#"%#",dateWithTime2);
//block starts here
void(^notificationBlock)(void) = ^{
appDelegate.localNotification1 = [UILocalNotification new];
appDelegate.localNotification1.fireDate = dateWithTime1;
appDelegate.localNotification1.applicationIconBadgeNumber = [[UIApplication sharedApplication]applicationIconBadgeNumber]+1;
if(dateWithTime2 != nil){//Make a new UILocalNotification object
appDelegate.localNotification2 = [UILocalNotification new];
appDelegate.localNotification2.fireDate = dateWithTime2;
appDelegate.localNotification2.applicationIconBadgeNumber = [[UIApplication sharedApplication]applicationIconBadgeNumber]+1;
}
if(dateWithTime3 !=nil){//MAke a new UILocalNotification object
appDelegate.localNotification3 = [UILocalNotification new];
appDelegate.localNotification3.fireDate = dateWithTime3;
appDelegate.localNotification3.applicationIconBadgeNumber = [[UIApplication sharedApplication]applicationIconBadgeNumber]+1;
}
if([_repeatDaysTextField.text isEqualToString:#"Everyday"]){
// appDelegate.localNotification1.alertBody = #"Time to take your medicine";
appDelegate.localNotification1.repeatInterval = kCFCalendarUnitDay;
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification1];
if(dateWithTime2 != nil){
appDelegate.localNotification2.repeatInterval = kCFCalendarUnitDay;
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification2];
appDelegate.localNotification2.alertBody = #"Not2";
NSLog(#"%#",appDelegate.localNotification2);
}
NSLog(#"%#",[NSString stringWithFormat:#"%#",dateWithTime3 ]);
if(dateWithTime3 != nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification3];
}
}
else if([_repeatDaysTextField.text isEqualToString:#"Alternately"]){
}
else if([_repeatDaysTextField.text isEqualToString:#"Weekly"]){
appDelegate.localNotification1.repeatInterval = kCFCalendarUnitWeekday;
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification1];
if(dateWithTime2!=nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification2];
}
if(dateWithTime3!=nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification3];
}
}
else if([_repeatDaysTextField.text isEqualToString:#"Bi-Weekly"]){
}
else if([_repeatDaysTextField.text isEqualToString:#"Monthly"]){
appDelegate.localNotification1.repeatInterval = kCFCalendarUnitMonth;
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification1];
if(dateWithTime2!=nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification2];
}
if(dateWithTime3!=nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification3];
}
}
else if([_repeatDaysTextField.text isEqualToString:#"Yearly"]){
appDelegate.localNotification1.repeatInterval = kCFCalendarUnitYear;
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification1];
if(dateWithTime2!=nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification2];
}
if(dateWithTime3!=nil){
[[UIApplication sharedApplication]scheduleLocalNotification:appDelegate.localNotification3];
}
}
};
//block ends here
//method to set notification
[self setNotification:notificationBlock];
}
-(void)setNotification:(void(^)(void))setNotificationBlock{
setNotificationBlock();
}
I got the solution.In the method,didReceiveLocalNotification:,I was adding the notification object to the 'scheduledNotifications' array.So every time a notification was scheduled,the same object was being added to the 'scheduledNotifications' array and that was getting fired again and again.
[UIApplication sharedApplication]scheduledNotifications = notification;
NOTE:Ignore this statement in didReceiveLocalNotification:
This is occuring beacuse you are setting
appDelegate.localNotification.repeatInterval = someUnit;
try setting the repeatInterval value to 1 by checking whether the repeatCount is 0 or not.

How do I make UILocalNotification method keep running

I am trying to build a calendar style app that reminds people when certain events are happening the day before they happen.
I am using UILocalNotifications for this.
I have to restart my app if I want the notification to appear.
How can I have this code continuously run regardless if the app is still running or is closed, and display the notification on time?
I was wondering if I had to put this into the applicationDidEnterBackground method to make it work?
Currently my code looks like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMMM dd, yyyy"];
NSString* path = [[NSBundle mainBundle] pathForResource:#"example"
ofType:#"txt"];
NSString* content = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:NULL];
NSArray* allLinedStrings = [content componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
NSDate *tomorrow = [today dateByAddingTimeInterval:60*60*24*1];
NSString *tomorrowString = [dateFormatter stringFromDate:tomorrow];
for (int i = 0; i < allLinedStrings.count; i++) {
NSString* strsInOneLine = [allLinedStrings objectAtIndex:i];
NSArray* singleStrs = [strsInOneLine componentsSeparatedByCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString:#";"]];
NSString *date = [singleStrs objectAtIndex:0];
if ([date isEqualToString:tomorrowString]) {
for (int j = 1; j < singleStrs.count; j+=2) {
UILocalNotification *notification = [[UILocalNotification alloc]init];
notification.fireDate = [NSDate dateWithTimeInterval:60*60*-24 sinceDate:tomorrow];
notification.alertBody = [singleStrs objectAtIndex:j+1];
notification.alertTitle = [singleStrs objectAtIndex:j];
notification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication]scheduleLocalNotification:notification];
}
}
}
// Override point for customization after application launch.
return YES;
}
Your app code does not need to be running for your local notification to be displayed. Once your app has called scheduleLocalNotification:, the notification will display whether or not you app is running.
If you app is in the foreground, you will also want to implement application:didReceiveLocalNotification:. If you want your app to respond to being opened by the user interacting with the notification, you will want to implement application:handleActionWithIdentifier:forLocalNotification:completionHandler:
As to the question of where to put the code that schedules the notification, it should go anywhere in your app that knows the event to be scheduled. It only needs to be called once per notification. It can be scheduled far in advance.

Local Notification Ever Changing Text

I am working on getting local notifications to fire at a time every day (set by the user). I have done this in the past, but just where it was one static message that would get shown every day. I would like for it to take the text for the local notification from a plist file I have made with each row being a quote. Is there a way to fire local notifications, but have it change the text every day?
I have right now:
- (IBAction)scheduleNotification {
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
UILocalNotification *notif = [[cls alloc] init];
notif.fireDate = [datePicker date];
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.alertBody = #"Today's 5 Minutes With God Study Is Now Available";
notif.alertAction = #"Ok";
notif.soundName = UILocalNotificationDefaultSoundName;
notif.applicationIconBadgeNumber = 1;
NSInteger index = [scheduleControl selectedSegmentIndex];
switch (index) {
case 0:
notif.repeatInterval = NSDayCalendarUnit;
break;
case 1:
notif.repeatInterval = 0;
break;
}
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"Today's Quote!"
forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[self.notifications addObject:notif];
[notif release];
}
}
So, how would I get the alertBody to show a different message each day?
You have to create a new notification every time, for every new message.

Comparing uipickerdate to current date

Here is the code that I have for my two datepickers which I need to compare them to the current date with an if condition or a switch.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
dateFormatter.timeZone=[NSTimeZone defaultTimeZone];
dateFormatter.timeStyle=NSDateFormatterShortStyle;
dateFormatter.dateStyle=NSDateFormatterShortStyle;
NSString *dateTimeString=[dateFormatter stringFromDate:startTime.date];
NSLog(#"Start time is %#",dateTimeString);
NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc]init];
dateFormatter2.timeZone=[NSTimeZone defaultTimeZone];
dateFormatter2.timeStyle=NSDateFormatterShortStyle;
dateFormatter2.dateStyle=NSDateFormatterShortStyle;
NSString *dateTimeString2=[dateFormatter2 stringFromDate:endTime.date];
NSLog(#"End time is %#",dateTimeString2);
in my .h
#property (weak, nonatomic) IBOutlet UIDatePicker *startTime;
#property (weak, nonatomic) IBOutlet UIDatePicker *endTime;
How do I do that? Do I need to store them to an NSDate or NSTime since I only really need the time?
Also, is there an If range in Objective C?
Thanks,
Just add this:
if ([[NSDate date] isEqualToDate:startTime.date]) {
NSLog(#"currentDate is equal to startTime");
}
if ([[NSDate date] isEqualToDate:endTime.date]) {
NSLog(#"currentDate is equal to endTime");
}
If you want to calculate interval between two dates use this method
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
if([startTime.date timeIntervalSinceDate:[NSDate date]] > 0)
{
//start time greater than today
}
else if([startTime.date timeIntervalSinceDate:[NSDate date]] < 0)
{
//start time less than today
}
else
{
//both dates are equal
}
For knowing when the application has entered background use notifications add this statement in your viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationEnteredBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
Add function to cater the notification when it is posted
-(void)applicationEnteredBackground
{
//do all the above steps here when you want.
}
And in dealloc function of the class remove observer for notification
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
The only dates I see in your code are startTime.date and endTime.date. I don't know where you are getting those, but they are presumably NSDates. The current date, on the other hand, is [NSDate date]. Hence you can compare using NSDate's compare: method or any of several other comparison methods (see the NSDate documentation).
NSDate implements isEqualToDate: which tests if two dates are the same down to the microsecond. It also implements earlierDate: and laterDate: which you can use to build a range check.
You could also build some helpers that let you control the sensitivity of equality check using timeIntervalSinceDate:. There's no date range object, but you could add a between check to your helpers, too...
#interfce NSDate (Comparison)
- (BOOL)isEqualToDate:(NSDate *)aDate within:(NSTimeInterval)tolerance;
- (BOOL)isBetween:(NSDate *)start and:(NSDate *)end within:(NSTimeInterval)tolerance;
#end
#implementation NSDate (Comparison)
- (BOOL)isEqualToDate:(NSDate *)aDate within:(NSTimeInterval)tolerance {
NSTimeInterval difference = [self timeIntervalSinceDate:aDate];
return fabs(difference) < tolerance;
}
- (BOOL)isBetween:(NSDate *)start and:(NSDate *)end within:(NSTimeInterval)tolerance {
NSTimeInterval startDifference = [self timeIntervalSinceDate:start];
if (startDifference < tolerance) return NO;
NSTimeInterval endDifference = [end timeIntervalSinceDate:self];
if (endDifference < tolerance) return NO;
return YES;
}
#end
I haven't tested these.
you can also do like below by using NSDate's compare: method,
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MM-dd-yyyy"];
NSDate* date1 = [df dateFromString:#"12-23-2046"];
NSDate *date2 = [NSDate date];
if ([date1 compare:date2] == NSOrderedSame){
NSLog(#"Same");
}
if ([date2 compare:date1]==NSOrderedAscending ) {
NSLog(#"AScending");
}
if ([date2 compare:date1]== NSOrderedDescending) {
NSLog(#"Descending");
}
take your startTime,endTime instead of date1,hope it will helps you.

Resources