I have several toggles assigned to sounds. When switched on, a short clip plays for 30 seconds or so. Then when switching between viewcontrollers inside the app (eg, to the menu page) when i go back to the toggles they are all off! I would like them to retain their value after being switched on until the user decides to turn them off. This is not an issue until switching between pages inside the app.
Thanks for your help.
-(void)kickSwitchChanged:(UISwitch*)sw
{
AppDelegate* app = [[UIApplication sharedApplication] delegate];
[app setKickStep:sw.tag state:sw.isOn];
}
-(void)snareSwitchChanged:(UISwitch*)sw
{
AppDelegate* app = [[UIApplication sharedApplication] delegate];
[app setSnareStep:sw.tag state:sw.isOn];
}
What you have sounds like a good use case for NSUserDefaults.
NSUserDefaults allows you to store data that will be persisted all the way through terminating and relaunching your app. It is meant to be used for "lighter-weight" data, like if a user wants a switch on or off.
Here is an example of saving a boolean default:
let kMySwitchDefaultKey = "isMySwitchOn"
NSUserDefaults.standardUserDefaults().setBool(mySwitch.on, forKey: kMySwitchDefaultKey)
Here is an example of retrieving the same boolean default:
let wasMySwitchOn = NSUserDefaults.standardUserDefaults().boolForKey(kMySwitchDefaultKey)
Typically you would set the default when the user changes the switch value, and you would get the default somewhere like viewWillAppear and use the saved value to update the switch state to be what it previously was set to.
Source: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html
Edit
I didn't see your Obj-C tag. Here is the same setting and getting code in Obj-C.
Setting
NSString* const kMySwitchDefaultKey = #"isMySwitchOn";
[[NSUserDefaults standardUserDefaults] setBool:mySwitch.on forKey:kMySwitchDefaultKey];
Getting
BOOL wasMySwitchOn = [[NSUserDefaults standardUserDefaults] boolForKey:kMySwitchDefaultKey];
Related
Can someone help with a method of how to launch into a view that an might have quit in or suspended in. E.g.
I launch the app.
Go Open a couple of views within the a and end up in View 4.
Quite the app or go into background mode.
I have read that NSUserDefaults can be used but I am just not sure how.
You can save the view in the userdefaults with:
NSString *valueToSave = #"view4";
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"lastView"];
[[NSUserDefaults standardUserDefaults] synchronize];
And then you can load the last view from the userdefaults when the user starts your app again (e.g. in the ViewDidLoad in your startView).
NSString *savedValue = [[NSUserDefaults standardUserDefaults]
stringForKey:#"lastView"];
After that you navigate to the view depending on the savedValue.
Keep in mind that you don't really save a view or something. You just save a short string or value that allows you to know which view you want to load again.
Update in Swift:
To save the last view:
let valueToSave = "view4"
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setValue(valueToSave, forKey: "lastView")
userDefaults.synchronize()
And after the restart of the app:
if let loadedView = userDefaults.valueForKey("lastView") {
// load your view
}
else {
// no last view saved
}
I recently found how to program a switch and how to change the background from 1 view.
My question is how to change the background of multiple views (UIImage) when changing the value of the switch.
For example: It's a preference page and when I switch the background of the preferences page changes so the switch works.
Now i want the background (UIImage) of my first view named "viewcontroller" to change to the same background as the background of my preferences page.
in my opinion, there may be a lot of different ways to achieve this. What i would do is save the image name string into [NSUserDefaults standardUserDefaults].
Such as when the switch value changes, you call
[[NSUserDefaults standardUserDefaults] setObject:#"BackgroundImageName" forKey:#"BackgroundImageOne.jpg"];
[[NSUserDefaults standardUserDefaults]synchronize];
and when you set up the background, you could do
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
UIImage *bgImage;
if ([userDefault objectForKey:#"BackgroundImageName"])
bgImage = [UIImage imageNamed:[userDefault objectForKey:#"BackgroundImageName"]];
else
bgImage = [UIImage imageNamed:#"DEFAULT_NAME"];
//... Set the bgImage to your background image view ...//
Maybe you have to do some changes based on the actual usage. But hope this give you some hints.
One of possible solutions would be to create a public property of application delegate holding your background image.
#property (strong) UIImage *globalBackground;
In your - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions you should initialize it either to some default image or last saved image.
self.globalBackground = [UIImage imageNamed:#"defaultBackground"];
Let's say your appDelegate header file is MyAppDelegate.h. You should import it in all the classes that use this default background image mechanism. Or simply add it to your Prefix.pch file.
In your settings view controller you would then set:
//your background setting handler
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.globalBackground = ... //however you get the selected image
//and here you set the background image of settings view controller
Then in each of the view controllets viewWillAppear: you set its background in similar manner:
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
//then you use appDelegate.globalBackground the same way you are doing it now
If you have a lot of view controllers you might want to consider creating a subclass of UIViewController that implements this mechanism (possibly calling it UIViewControllerWithBackground) and make all your view controllers subclasses of this class.
Note A: one would (instead of appDelegate's property) typically use a singleton class holding all the settings. It might be considered as a bad (quick & dirty) practice. More...
Note B: for saving the name of last selected background you could use NSUserDefaults. This is out of the scope of this question and there is a lot of sample code available out there...
Is it possible to pass the image, which I saved in Xcode, to a next viewcontroller? Or give it a number and pass that number to a next viewcontroller? For example, when switchone is on, NSNumber = 1, pass it to the next view, and then if (NSNumber == 1) than display "backgroundone.jpg"???
This question already exists:
Load up different view on first run
Closed 9 years ago.
I'm programming an app at the moment which requires on the first run for the app toload a different view in which the user can select its prefered settings.Here's the code
implementation AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// Determining Storyboard identifier for first view
// Determining Storyboard identifier for first view
NSString *storyboardID = [self hasEverBeenLaunched]? #"MainView" : #"LoginView";
// Setting proper view as a rootViewController
self.window.rootViewController = [self.window.rootViewController.storyboardinstantiateViewControllerWithIdentifier: #"view45"] ;
It then goes on with the following code:
- (BOOL)hasEverBeenLaunched
{
// A boolean which determines if app has eer been launched
BOOL hasBeenLaunched;
// Testig if application has launched before and if it has to show the home-login screen to login
// to social networks (facebook, Twitter)
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasAlreadyLaunched"]) {
// Setting variable to YES because app has been launched before
hasBeenLaunched = YES;
NSLog(#"App has been already launched");
} else {
// Setting variable to NO because app hasn't been launched before
hasBeenLaunched = NO;
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasAlreadyLaunched"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"This is the first run ever...");
}
return hasBeenLaunched;
}
Just a few quick notes: View 45 is the initial starting up view which should only show once, Otherwise the main view controller is ticked under atrributes to be the initial view controller(The one that always loads up at the start, after the first run)
So the problem is that it only ever loads view 45 ,the first run view, but whats causing that exactly ?
The problem is in the following line:
self.window.rootViewController = [self.window.rootViewController.storyboardinstantiateViewControllerWithIdentifier: #"view45"] ;
It is ignoring the value of storyboardID and just using the string #"view45", so that's why you'll always get the same one every single time.
If you want to fix it, change it to the following line:
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardID];
You can see that now it is making use of the value in storyboardID.
So one of the users in here managed to show me how to pass data from a child view controller to a parent view controller via a string.
So now the string is passed, BUT, i want that value to stay displayed on the firstViewController after the app is closed and re-opened.
The value is saved in with NSUserDefaults by the way and with an NSLog i am seeing on the conosole it is saved in the apps folder but that value isnt saved onto the UILabel display.
It only displays it when i put save but then i close and reopen, it dissappears but in an NsLog it is still inside the app but not on display UILabel.
How can i address this ?
On my appDelegate.h i have a
#property (strong, nonatomic) NSString *sharedString;
To pass the secondViewController data to the firstViewController.
In the save method on my secondViewController i have a function related to the
AppDelegate.h declaration which is:
AppDelegate *apiDelegate = [[UIApplication sharedApplication] delegate]
apiDelegate.sharedString = self.textFieldData.text;
And in my firstViewController i have a method which display the data from the second
viewController:
-(void) viewDidAppear:(BOOL)animated {
AppDelegate *apiDelegate = [[UIApplication sharedApplication] delegate]
self.DisplayData.text = appDelegate.sharedString;
[super viewDidAppear: NO];
Is there something wrong which isnt keeping the data intact after app closes or am
I missing something here ?
So one of the users in here managed to show me how to pass data from a
child view controller to a parent view controller via a string.
First you need to establish some hierarchy as to how you get a childViewController from a parentViewController. One way to pass data from childViewController to parentViewController is using a delegate. The other could be using the KVC/KVO protocol. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html
In this you can simply register an observer for the property defined in the childViewController and observe it's changes wherever you want (well, given the hierarchy is satisfied).
To save the value. You can simply save it using NSUserDefaults. I don't see any code in your post but you can simply define a key and save the value with NSUserDefaults using:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:sharedString forKey:#"sharedString"];
NSString *sharedStringFromDefaults = [defaults objectForKey:#"sharedString"];
Also,
AppDelegate *apiDelegate = [[UIApplication sharedApplication]
delegate]
Apple requires you to avoid such references in the application. It only constrains the app. Further, the sharedString is not required to be in the AppDelegate. Otherwise the AppDelegate will be filled with almost every other data structure you have shared in the app.
//add this code when you want to store string
[[NSUserDefaults standardUserDefaults] setObject:self.textFieldData.text forKey:#"sharedString"];
[[NSUserDefaults standardUserDefaults] synchronize];
//and when you want string than
self.DisplayData.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"sharedString"];
I want to show a help overlay when a user runs my application for the first time.
To do this, I'm using the following code indidFinishLaunching:
if(![[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:#"IPHONEFIRSTRUN"])
[[NSUserDefaults standardUserDefaults]setBool:TRUE forKey:#"IPHONEFIRSTRUN"];
In the view controller, I have:
if ([[NSUserDefaults standardUserDefaults]boolForKey:#"IPHONEFIRSTRUN"]==TRUE) {
[self HelpOverlayIphone];
[[NSUserDefaults standardUserDefaults]setBool:FALSE forKey:#"IPHONEFIRSTRUN"];
}
However, it shows the overlay on the second use as well. How can I fix this? Any help is appreciated.
Your logic is overly complex. You are setting permanently a user default to indicate something happening one time. Instead, in the view controller see if the value is not set, if it is do your action and set the variable so that the code is NOT run again:
if ( ! [[NSUserDefaults standardUserDefaults]boolForKey:#"IPHONEFIRSTRUNCOMPLETE"] ) {
[self HelpOverlayIphone];
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"IPHONEFIRSTRUNCOMPLETE"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Take out all the code in the app delegate.
Also it's very likely your original code is not working because you are stopping the app from XCode. If you don't use synchronize user default changes will not be saved in that case (normal quitting of the app does eventually save the changes permanently).
Have you registered the defaults you are using at the start of the program? I would suggest rereading the apple documentation for NSUserDefaults here
You need to first make a call to
- (void)registerDefaults:(NSDictionary *)dictionary
which will only set the key if it doesn't already exist. Then check the key for falseness on the the first run and set it at this point.
My guess is the reason your code isn't working is because the dictionary is never actually being saved in any sort of persistent way.
I have this function which fires when the app fires up- it's always been reliable. I have a uniqueNameOfApp which is just some random hash so that it doesn't collide with other apps.
-(void)loadSettings {
NSMutableDictionary *sttngs = [[NSUserDefaults standardUserDefaults]
objectForKey:uniqueNameOfApp];
if(sttngs != nil) {
[userSettings addEntriesFromDictionary:sttngs];
} else {
_appFiredForFirstTime = YES;
}
}