I made an UISwitch, and when it is switched on, my app sends 10 notifications with a "repeat interval". It works all fine. But the problem is, when I want to save (remember) the state of my UISwitch and load it, the UILocalNotification aren't being sent anymore.
This is my code:
For the save of the UISwitch state and notification launch:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
BOOL test= [[NSUserDefaults standardUserDefaults] boolForKey:#"switch"];
NSLog(#"%#",test?#"YES":#"NO");
[self.alarmSwitch setOn:test animated:YES];
}
- (void) switchIsChanged:(UISwitch *)paramSender{
if ([paramSender isOn]){
[[NSUserDefaults standardUserDefaults] setBool:self.alarmSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
notification1 = [[UILocalNotification alloc]init];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
[notification1 setAlertBody:#"U moet uw voeten controleren!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:10.0];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
}
}
How can I save the state of the UISwitch in another way in order to get this work? Or is there another solution to fix this?
Your switchIsChanged: method isn't going to be firing when you set the on state programatically. I would recommend moving the code that handles the notifications out of the switchIsChanged: method. Example:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
BOOL test= [[NSUserDefaults standardUserDefaults] boolForKey:#"switch"];
NSLog(#"%#",test?#"YES":#"NO");
[self.alarmSwitch setOn:test animated:YES];
// initially detect if we should fire the bnotifications
if ([self.alarmSwitch isOn]) {
[self fireNotifications];
}
}
-(void)switchIsChanged:(UISwitch *)paramSender{
[[NSUserDefaults standardUserDefaults] setBool:paramSender.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
if ([paramSender isOn]){
[self fireNotifications];
}
}
-(void)fireNotifications {
notification1 = [[UILocalNotification alloc]init];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
[notification1 setAlertBody:#"U moet uw voeten controleren!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:10.0];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
}
Note: you may have to make sure that the notifications aren't firing more than once which may cause bugs since viewWillAppear: can be called multiple times.
Related
I'm implementing local notifications,there are 3 notifications to be send at different times of a day.
in my app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
}
and in DidReceiveLocalNotifications
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
NSString *checkbtn= [[NSUserDefaults standardUserDefaults]valueForKey:#"on"];
if([checkbtn isEqualToString:#"SwitchOn"])
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Green Actions"
message:notification.alertBody
delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
// Set icon badge number to zero
application.applicationIconBadgeNumber = 0;
//}
}
if i remove this alert view,i m not getting any notification in foreground but if i use this then i m getting notification alert every second.
this is my viewcontroller code
- (void)viewDidLoad {
[super viewDidLoad];
appdelegate= (AppDelegate *) [[UIApplication sharedApplication]delegate];
[self createCustomeNavigationBar];
self.navigationController.navigationBar.translucent = NO;
//[self notificationOne];
[self.switchbutton addTarget:self action:#selector(switchToggled:) forControlEvents:UIControlEventValueChanged];
[self.switchbutton1 addTarget:self action:#selector(switchToggled1:) forControlEvents:UIControlEventValueChanged];
[self.switchbutton3 addTarget:self action:#selector(switchToggled3:) forControlEvents:UIControlEventValueChanged];
if ([[NSUserDefaults standardUserDefaults]valueForKey:#"on"])
{
UILocalNotification* n1 = [[UILocalNotification alloc] init];
n1.fireDate = [NSDate dateWithTimeIntervalSinceNow: 160];
n1.alertBody = #"one";
[[UIApplication sharedApplication] scheduleLocalNotification: n1];
}
if ([[NSUserDefaults standardUserDefaults]valueForKey:#"SwitchOneon"])
{
UILocalNotification* n2 = [[UILocalNotification alloc] init];
n2.fireDate = [NSDate dateWithTimeIntervalSinceNow: 190];
n2.alertBody = #"two";
[[UIApplication sharedApplication] scheduleLocalNotification: n2];
}
// Do any additional setup after loading the view from its nib.
}
- (void) switchToggled:(id)sender {
self.switchbutton = (UISwitch *)sender;
if ([self.switchbutton isOn]) {
NSLog(#"its on!");
[[NSUserDefaults standardUserDefaults]setObject:#"SwitchOn" forKey:#"on"];
[[NSUserDefaults standardUserDefaults]synchronize];
} else {
[[NSUserDefaults standardUserDefaults]removeObjectForKey:#"on"];
NSLog(#"its off!");
}
}
- (void) switchToggled1:(id)sender {
self.switchbutton1 = (UISwitch *)sender;
if ([self.switchbutton1 isOn]) {
NSLog(#"its on!");
[[NSUserDefaults standardUserDefaults]setObject:#"SwitchOn" forKey:#"SwitchOneon"];
[[NSUserDefaults standardUserDefaults]synchronize];
} else {
[[NSUserDefaults standardUserDefaults]removeObjectForKey:#"SwitchOneon"];
NSLog(#"its off!");
}
}
- (void) switchToggled3:(id)sender {
self.switchbutton3 = (UISwitch *)sender;
if ([self.switchbutton3 isOn]) {
NSLog(#"its on!");
[[NSUserDefaults standardUserDefaults]setObject:#"SwitchOn" forKey:#"SwitchThreeon"];
[[NSUserDefaults standardUserDefaults]synchronize];
} else {
[[NSUserDefaults standardUserDefaults]removeObjectForKey:#"SwitchThreeon"];
NSLog(#"its off!");
}
}
and also i m getting some different text in alert view which i used earlier just for testing purpose,even after changing it,i m getting the same old previous text.
I am sure that problem isn't with alert code. - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification, you're getting notification. But when your app is in foreground (or active) you should handle it manually. In your case, you're handling it with UIAlertView so it will be visible in alert, but once you removed, you're not able to see a notification when your app was in foreground (or active) state.
I wish to make an app that, when the user opens it for the first time he selects his country from a picker in order to make his flag appear on the main screen. If the user closes the app and opens it again I want the app to start the menu screen with his flag on it directly.
I am using the following code now but it doesn't work at all. Every time the app is opened it takes him to the picker VIew (TappViewController)
- (void)viewDidLoad
{
[super viewDidLoad];
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"FirstLaunch"]) {
secViewController *menu = [[secViewController alloc] init];
[self presentViewController:menu animated:YES completion:^{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"FirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];}];
}
else{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"FirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Change your code like this:
- (void)viewDidLoad
{
[super viewDidLoad];
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"isPickerOpened"]) {
secViewController *menu = [[secViewController alloc] init];
[self presentViewController:menu animated:YES completion:^{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isPickerOpened"];
[[NSUserDefaults standardUserDefaults] synchronize];
}];
}
}
I want to use a UISwitch to enable/disable push notifications. Like in Tweetbot.
Does anyone know how to trigger that?
You can also do it in the following way.
create a IBOutlet for UISwitch
#property (strong, nonatomic) IBOutlet *pushNotificationSwitch;
and in Action method, store the value in NSUserDefaults.
- (IBAction)pushNotificationSwitchChanged:(id)sender
{
NSNumber *switch_value = [NSNumber numberWithBool:[self.pushNotificationSwitch isOn]];
[[NSUserDefaults standardUserDefaults] setObject:switch_value forKey:RECIEVE_APNS];
[[NSUserDefaults standardUserDefaults] synchronize];
}
and check it in viewdidload.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSNumber *sett = [[NSUserDefaults standardUserDefaults] valueForKey:RECIEVE_APNS];
if( [sett boolValue] )
{
[self.pushNotificationSwitch setOn:YES];
}
else{
[self.pushNotificationSwitch setOn:NO];
}
}
and In AppDelegate.m, add the following code
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSNumber *sett = [[NSUserDefaults standardUserDefaults] objectForKey:RECIEVE_APNS];
if( [sett boolValue] )
{
int currentBadgeCount = [[NSUserDefaults standardUserDefaults] integerForKey:#"BadgeCount"];
//Set the baadge count on the app icon in the home screen
int badgeValue = [[[userInfo valueForKey:#"aps"] valueForKey:#"badge"] intValue];
[UIApplication sharedApplication].applicationIconBadgeNumber = badgeValue + currentBadgeCount;
[[NSUserDefaults standardUserDefaults] setInteger:badgeValue + currentBadgeCount forKey:#"BadgeCount"];
NSString *alertString = [[userInfo objectForKey:#"aps"] objectForKey:#"alert"];
NSString *playSoundOnAlert = [NSString stringWithFormat:#"%#", [[userInfo objectForKey:#"aps"] objectForKey:#"sound"]];
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/%#",[[NSBundle mainBundle] resourcePath],playSoundOnAlert]];
NSError *error;
if (alertString.length > 0)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"App Name" message:alertString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = 1;
[audioPlayer play];
[alert show];
}
}
}
enter code here
You can not do that directly from the application. If you want to do this, you need to make the UISwitch send the information to your backend, store this information in your database and stop sending push notifications to this user.
An app registers for Push Notifications (APN) when it first launches. You cannot have it initialize APNs with a switch once it has already launched. You can however code your app that a switch can choose to do "something" with the user interface once a APN is received.
For example, you can have this code:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
NSString *alert = [apsInfo objectForKey:#"alert"];
// do what you need with the data...
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReceivedNotificationAlert" object:self];
}
You can use your UISwitch to either do something, or not, with the NSNotification "ReceivedNotificationAlert". For example:
if(switchAPNprocess.on){
// process APN
}
else {
// ignore APN
}
I have at timeout feature where if the app is idle (in background) for a period of time, I timeout my app and send the user to the login screen. I set the "timedOut" key in user defaults to YES in my application delegate, then reference that key in each view controller, where if it is YES, I segue to the login screen. On the login screen I have a label that displays "Session has timed out" if the "timedOut" is YES. My issue is that if I login, then logout very quickly, the label is displayed, even though I explicitly set that key to NO right after I show the label and then synchronize the user defaults. If I wait a second or two and logout, the label is hidden like it should be. I have solved the "problem", but would like to understand the behavior.
Code from view did load in my login view controller. You would think this changes the isTimedOut to NO, but when I do a quick logout viewdidload is called again, but isTimedOut is YES.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
sessionLabel.hidden = YES;
isTimedOut = [defaults boolForKey:#"isTimedOut"];
if (isTimedOut == YES)
{
sessionLabel.hidden = NO;
defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:NO forKey:#"isTimedOut"];
isTimedOut = NO;
NSLog(#"Timed Out has been reset to %s",[defaults boolForKey:#"isTimedOut"] ? "YES" : "NO");
[defaults synchronize];
}
UPDATE
I replaced the code above using a property in my app delegate instead of NSUserDefaults and the "strange" behavior went away.
eONavAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
isTimedOut = appDelegate.isTimedOut;
sessionLabel.hidden = YES;
//isTimedOut = [defaults boolForKey:#"isTimedOut"];
NSLog(#"Timed Out has been reset to %s",appDelegate.isTimedOut ? "YES" : "NO");
if (isTimedOut == YES)
{
appDelegate.isTimedOut = NO;
sessionLabel.hidden = NO;
}
MORE CODE
To logout, I have UIButtonBarItem calling a segue programmatically. The doLogout property tells the login view controller to run a logout API.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"logoutSegue"])
{
// Get reference to the destination view controller
eoLoginViewController *vc = [segue destinationViewController];
vc.doLogout = YES;
}
}
isTimedOut is set in one location in the app delegate.
-(void)timeoutWithDate:(NSDate *)currentDate
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate *previousDate = [defaults objectForKey:#"enteredBackground"];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:previousDate];//TimeInterval is in seconds
NSLog(#"Time between dates in seconds %f",distanceBetweenDates);
double minutesInAnHour = 60;
double minutesBetweenDates = distanceBetweenDates / minutesInAnHour;
NSLog(#"minutesBetweenDates %f",minutesBetweenDates);
if(minutesBetweenDates > 60)
{
isTimedOut = YES;
}
else
{
isTimedOut = NO;
}
}
Use this:
To save a Bool:
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"isTimedOut"];
To Load a Bool:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"isTimedOut"] == YES) {
//it equals yes
}
else {
//it equals no
}
why don't you try something like this? I didn't see your full project but it should work like a charm.
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
then...
- (void)applicationWillResignActive:(UIApplication *)application
{
[[NSUserDefaults standardUserDefaults] setValue:[NSDate date] forKey:#"sleepTime"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
and...
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSInteger _timeoutInSeconds = 300;
NSDate *_sleepTime = [[NSUserDefaults standardUserDefaults] valueForKey:#"sleepTime"];
if (_sleepTime) {
NSCalendar *_calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *_dateComponents = [_calendar components:NSSecondCalendarUnit fromDate:_sleepTime toDate:[NSDate date] options:0];
if (_dateComponents.second > _timeoutInSeconds) {
// expired session
} else {
// valid session
}
}
}
Developing for a jailbroken device.
I've looked here for a soultion to my problem. Using NSUserDefaults for storing UISwitch state but people say alot of the codes don't work.
I'm using a UISwitch to load/unload a launch daemon for iOS. I've gotten very close but the switch state won't save. This is the code im using.
#synthesize toggleSwitch;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if([[NSUserDefaults standardUserDefaults] boolForKey:#"switch"]) toggleSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"switch"];
}
- (void)switchValueChanged {
if (toggleSwitch.on) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:TRUE];
switchlabel.text = #"Enabled";
const char *onchar = [[NSString stringWithString:#"launchctl load -wF /System/Library/LaunchDaemons/com.launch.daemon.plist"] UTF8String];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE];
setuid(0); system(onchar);
if (system(onchar) == 0){
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE];}
} else {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:TRUE];
switchlabel.text = #"Disabled";
const char *offchar = [[NSString stringWithString:#"launchctl unload -wF /System/Library/LaunchDaemons/com.launch.daemon.plist"] UTF8String];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE];
setuid(0); system(offchar);
if (system(offchar) == 0){
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE]; }
}
The bool value is written in my app plist. I don't seem to know what I did wrong. I pieced afew examples from questions on overflow with no luck. Regardless if the command fails, the switch should save.
Could someone explain and show me what should be edited. This has been driving me absolutely nuts.