So guys, i've been trying literally for the last week to get this to work.
I have a app that i need a UISwitch to turn on a local notification.
Standard for the switchs state is off, but i need to change this, on load, when the alarm is on.
I've tried scheduledLocalNotification, i've tried a BOOL and i've tried to set int isOn, to 1 when it's on and 0 when it's off, nothing seems to be working for me.
The if loop i use is in ViewDidLoad and looks like this:
if (isAlarmOn == 1) {
NSLog(#"You have notifications");
[setAlarm setOn:YES];
}
else{
NSLog(#"You have no notifications");
[setAlarm setOn:NO];
}
No matter which strategy i try to use, i doesn't seem to work, hope i can get some help from your guys.
Some more code:
The code for my setAlarm
- (IBAction)setAlarm:(id)sender {
NSArray *notificationArray=[[UIApplication sharedApplication] scheduledLocalNotifications];
if (setAlarm.on) {
[alarmStatus setText:#"Alarmen er tændt"];
//Metode til at undersøge om klokken før eller efter officiel solned
NSTimeInterval checkTime = [[astronomicalCalendar sunset] timeIntervalSinceDate:[NSDate date]];
NSLog(#"Alarmen er tændt");
if (checkTime >= 0) {
[self scheduleNotificationToday];
}
else{
[self scheduleNotificationTomorrow];
}
NSLog(#"antal alamer %#", notificationArray);
isAlarmOn = 1;
}
else {
//Metode til at slette alle notifikationer
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSLog(#"Alarmen er slukket");
NSLog(#"antal alamer %#", notificationArray);
isAlarmOn = 0;
}
}
My UILocalNotification code
- (void)scheduleNotificationToday {
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
//Just some stuff determine which time to alert on.
UILocalNotification *notif = [[cls
alloc] init];
notif.fireDate = [gregorian dateByAddingComponents:traekFraDag toDate:[astronomicalCalendar sunset] options:0];
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.alertBody = #"Nu går solen snart ned";
notif.alertAction = #"Show me";
notif.soundName = #"Waterline.caf";
notif.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
}
}
Please tell me if there is any other part of the code you would like to see
You need to post more code to give us better context on what these variables are and what your question actually is, but I think you might be looking for:
[setAlarm setOn:YES animated:YES];
and
[setAlarm setOn:NO animated:YES];
..if setAlarm is your switch name??
Make sure that setAlarm really does point to the switch, i.e. it's not nil and it doesn't point to some other switch. And please choose some other name for your variable! ;-)
Also, make sure that you don't have code in -viewWillAppear or some other method that's called after -viewDidLoad that resets the switch's value. In fact, you might want to defer setting up the switch and other UI elements until -viewWillAppear.
but every time the app is unloaded from the memory the uiswitch shows
the default state (off)
You are not storing the state of your switch in any persistant store. That is why it always shows as off if the app exits (dealloc is called for your class).
If you want to save the switch state even when the app is not in memory, then you'll need to save that value somewhere. You can use NSUserDefaults for this if you want.
Related
I am working on time based reminder App. in which the user enter his reminder and time for the reminder. The problem is that how to continuously comparing the current time with the user defined time. Any sample code will greatly help. because i am stuck on this point.
Comparing the current time vs. the user defined one is not the right design pattern.
UIKit offers the NSLocalNotification object that is a more high-level abstraction for your task.
Below is a snip of code that create and schedule a local notification at the choosen time:
UILocalNotification *aNotification = [[UILocalNotification alloc] init];
aNotification.fireDate = [NSDate date];
aNotification.timeZone = [NSTimeZone defaultTimeZone];
aNotification.alertBody = #"Notification triggered";
aNotification.alertAction = #"Details";
/* if you wish to pass additional parameters and arguments, you can fill an info dictionary and set it as userInfo property */
//NSDictionary *infoDict = //fill it with a reference to an istance of NSDictionary;
//aNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:aNotification];
[aNotification release];
Also, be sure to setup your AppDelegate to respond to local notifications, both at startup and during the normal runtime of the app (if you want to be notified even the application is in foreground):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification *aNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey];
if (aNotification) {
//if we're here, than we have a local notification. Add the code to display it to the user
}
//...
//your applicationDidFinishLaunchingWithOptions code goes here
//...
[self.window makeKeyAndVisible];
return YES;
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
//if we're here, than we have a local notification. Add the code to display it to the user
}
More details at the Apple Developer Documentation.
Why not use NSLocalNotification which you can set for a specified time, much like a calendar event. Alternatively you can add calendar events to the users calendar with EKEventKit
Tutorial for local notifications.
Tutorial for event kit.
Reposting with more concise and focused question after original question went unanswered. Also adding more insight into the problem after another day of research:
In my app delegate (didFinishLaunching), I set up a callEventHandler on CTCallCenter.
The idea is that when a callState changes, I post a notification with a userInfo dict
containing the call.callState. In my view, I observe this notification, and when the
userInfo dict contains a value of CTCallDisconnected, I want to unhide a view.
The problem I'm having is that the unhiding aspect is taking, almost consistenly, ~ 7 seconds.
Everything else is working fine, and I know this because I NSLog before and after the unhiding,
and those logs appear immediately, but the darned view still lags for 7 seconds.
Here's my code:
appDidFinishLaunching:
self.callCenter = [[CTCallCenter alloc] init];
self.callCenter.callEventHandler = ^(CTCall* call) {
// anounce that we've had a state change in our call center
NSDictionary *dict = [NSDictionary dictionaryWithObject:call.callState forKey:#"callState"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"CTCallStateDidChange" object:self userInfo:dict];
};
I then listen for this notification when a user taps a button that dials a phone number:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ctCallStateDidChange:) name:#"CTCallStateDidChange" object:nil];
Then, in ctCallStateDidChange:
- (void)ctCallStateDidChange:(NSNotification *)notification
{
NSLog(#"121");
NSString *callInfo = [[notification userInfo] objectForKey:#"callState"];
if ([callInfo isEqualToString:CTCallStateDisconnected]) {
NSLog(#"before show");
[self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
NSLog(#"after show");
}
}
I've tracked the problem down to the if condition in the above code sample:
if ([[userInfo valueForKey:#"userInfo"] valueForKey:#"callState"] == CTCallStateDisconnected) {
If I simply replace that with:
if (1 == 1) {
Then the view appears immediately!
The thing is, those NSLog statements are logging immediately, but the view is
lagging in it's unhiding. How could that condition cause only part of it's block
to execute immediately, and the rest to wait ~ 7 seconds?
Thanks!
Try changing your code to this:
- (void)ctCallStateDidChange:(NSNotification *)notification
{
NSLog(#"121");
NSString *callInfo = [[notification userInfo] objectForKey:#"callState"];
if ([callInfo isEqualToString:CTCallStateDisconnected]) {
NSLog(#"before show");
[self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
NSLog(#"after show");
}
}
Note:
The parameter is an NSNotification, not an NSDictionary
I would not compare strings with ==
No need to cast the view to change the hidden property
Use NO instead of false
Update: Got an idea: Could you try the following, please, in between the NSLogs?
dispatch_async(dispatch_get_main_queue(), ^{
[self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
});
Reading the CTCallCenter doc, it seems the callEventHandler is dispatched on "the default priority global dispatch queue", which is not the main queue where all the UI stuff happens.
Looks like there is no problem with your hidden code. If I were you, I would comment out all the code after the call ends, and uncomment them one by one to see what is the problem.
Hm... try to call [yourViewController.view setNeedsDisplay] after you change hidden property. Or avoid hidden, use alpha or addSubview: and removeFromSuperview methods instead.
djibouti33,
Where you put this sentence to listen when a user taps a button that dials a phone number?on WillResignActive function?
this sentence --> [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ctCallStateDidChange:) name:#"CTCallStateDidChange" object:nil];
Thanks for your time,
Willy.
Reposting with more concise and focused question after original question went unanswered. Also adding more insight into the problem after another day of research:
In my app delegate (didFinishLaunching), I set up a callEventHandler on CTCallCenter.
The idea is that when a callState changes, I post a notification with a userInfo dict
containing the call.callState. In my view, I observe this notification, and when the
userInfo dict contains a value of CTCallDisconnected, I want to unhide a view.
The problem I'm having is that the unhiding aspect is taking, almost consistenly, ~ 7 seconds.
Everything else is working fine, and I know this because I NSLog before and after the unhiding,
and those logs appear immediately, but the darned view still lags for 7 seconds.
Here's my code:
appDidFinishLaunching:
self.callCenter = [[CTCallCenter alloc] init];
self.callCenter.callEventHandler = ^(CTCall* call) {
// anounce that we've had a state change in our call center
NSDictionary *dict = [NSDictionary dictionaryWithObject:call.callState forKey:#"callState"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"CTCallStateDidChange" object:self userInfo:dict];
};
I then listen for this notification when a user taps a button that dials a phone number:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ctCallStateDidChange:) name:#"CTCallStateDidChange" object:nil];
Then, in ctCallStateDidChange:
- (void)ctCallStateDidChange:(NSNotification *)notification
{
NSLog(#"121");
NSString *callInfo = [[notification userInfo] objectForKey:#"callState"];
if ([callInfo isEqualToString:CTCallStateDisconnected]) {
NSLog(#"before show");
[self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
NSLog(#"after show");
}
}
I've tracked the problem down to the if condition in the above code sample:
if ([[userInfo valueForKey:#"userInfo"] valueForKey:#"callState"] == CTCallStateDisconnected) {
If I simply replace that with:
if (1 == 1) {
Then the view appears immediately!
The thing is, those NSLog statements are logging immediately, but the view is
lagging in it's unhiding. How could that condition cause only part of it's block
to execute immediately, and the rest to wait ~ 7 seconds?
Thanks!
Try changing your code to this:
- (void)ctCallStateDidChange:(NSNotification *)notification
{
NSLog(#"121");
NSString *callInfo = [[notification userInfo] objectForKey:#"callState"];
if ([callInfo isEqualToString:CTCallStateDisconnected]) {
NSLog(#"before show");
[self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
NSLog(#"after show");
}
}
Note:
The parameter is an NSNotification, not an NSDictionary
I would not compare strings with ==
No need to cast the view to change the hidden property
Use NO instead of false
Update: Got an idea: Could you try the following, please, in between the NSLogs?
dispatch_async(dispatch_get_main_queue(), ^{
[self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
});
Reading the CTCallCenter doc, it seems the callEventHandler is dispatched on "the default priority global dispatch queue", which is not the main queue where all the UI stuff happens.
Looks like there is no problem with your hidden code. If I were you, I would comment out all the code after the call ends, and uncomment them one by one to see what is the problem.
Hm... try to call [yourViewController.view setNeedsDisplay] after you change hidden property. Or avoid hidden, use alpha or addSubview: and removeFromSuperview methods instead.
djibouti33,
Where you put this sentence to listen when a user taps a button that dials a phone number?on WillResignActive function?
this sentence --> [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ctCallStateDidChange:) name:#"CTCallStateDidChange" object:nil];
Thanks for your time,
Willy.
I'm trying to clear my app's "unread" badge with a UILocalNotification. Logically you would think this would be done by setting applicationIconBadgeNumber of a UILocalNotification instance to 0. But it doesn't work, and the docs for applicationIconBadgeNumber say "The default value is 0, which means "no change.”"
So is there really no way to clear a badge with local notifications once it's been set?
Update: Some simple code:
-(void)applicationDidFinishLaunching
{
// Set the appication icon badge to 1 in 10 minutes, using a local notification so it works in the background:
// This works fine.
UILocalNotification *episodeNotification = [[UILocalNotification alloc] init];
episodeNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:(60 * 10)];
episodeNotification.timeZone = [NSTimeZone defaultTimeZone];
episodeNotification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:episodeNotification];
[episodeNotification release];
// Clear the application icon badge in 20 minutes, again using a local notifcation so it works in the background:
// This doesn't work. According to the docs for local notification it's not supposed to
// because (applicationIconBadgeNumber = 0) means "Do not change the badge"
// I'm looking for an alternative if it exists.
UILocalNotification *clearEpisodeNotification = [[UILocalNotification alloc] init];
clearEpisodeNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:(60 * 20)];
clearEpisodeNotification.timeZone = [NSTimeZone defaultTimeZone];
clearEpisodeNotification.applicationIconBadgeNumber = 0;
[[UIApplication sharedApplication] scheduleLocalNotification:clearEpisodeNotification];
[clearEpisodeNotification release];
}
I had the same problem. When setting the badge from a local notification, setting it to 0 is the default for 'no change', while doing it straight from the application would clear it. Setting it to a negative number through a local notification solved the problem.
try:
clearEpisodeNotification.applicationIconBadgeNumber = -1;
Yes, it is possible to clear the badge from the app itself.
I use the code below in one of my apps, and it works as expected (i.e. clears the badge):
//clear app badge
[UIApplication sharedApplication].applicationIconBadgeNumber=0;
I have some unsolved problem right now. My game is done, now I am at the last stage. In the main menu of the game there will be a button called goodies. Only appears when the user win the game once. I can do until that part . But the last part is to save that goodies. Meaning when the player exist the game after he able to make the button appear, the button still there when he gets back to the game? Could you guys help me out I am not quite sure how to do it. I heard a lot about NSUSerDefault, but don know how it works and how to apply it properly. Thanks for any help.
DegrafeurAppDelegate *appdelegate = (DegrafeurAppDelegate *) [[UIApplication sharedApplication] delegate];
//BOOL b = appdelegate.checkStatus;
if(appdelegate.checkStatus == YES)
{
[goodies setVisible:YES];
}
else
{
[goodies setVisible:NO];
}
This is my code to enable the button after winning once. But how to save it, please help me
As you mentioned, you can user NSUserDefaults:
NSUserDefaults myPrefs = [[NSUserDefaults alloc] init];
[myPrefs setBool:YES forKey:#"displayed_win_button"];
[myPrefs release];
and later to check the value:
if([myPrefs boolForKey:#"displayed_win_button"]) { ... }