Reputation: 153
I am trying to use NSUserdefaults to save some data from a text field, I want it to be saved when the application quits and loaded when the application starts, however I have run into a wall.
The methods that I want to use are all in the AppDelegate, Now I do not understand how to use AppDelegate very well, I have thought of two possible ways to achieve this, I have no idea if it would work though.
Any suggestions would appreciated
Thank you very much for your time
Upvotes: 6
Views: 6189
Reputation: 62686
Rather than keep the text field in your AppDelegate, keep the text. I'd do the following:
1) In AppDelegate.h:
@property (strong, nonatomic) NSString *textToBeSaved;
2) In AppDelegate.m, read and write textToBeSaved to NSUserDefaults when your app launches and terminates. On launch:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.textToBeSaved = [defaults objectForKey:@"save_me"];
and, before termination:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:self.textToBeSaved forKey:@"save_me"];
BOOL success = [defaults synchronize];
3) In SomeViewController.m that naturally owns the UITextField, in viewWillAppear:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
myTextField.text = appDelegate.textToBeSaved;
4) When you set the textToBeSaved depends on your UI, but whenever you know the text is ready (say on textFieldShouldReturn, or shouldEndEditing), you can hand the string to AppDelegate:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.textToBeSaved = myTextField.text;
If there's no UI to let the user accept the text, you can save the string on (textField:shouldChangeCharactersInRange:replacementString).
Upvotes: 4
Reputation: 70673
It's certainly allowed to have the App Delegate hold a reference to the view controller chain. Apple's own examples and iOS app templates often put a pointer to a root view controller in an App Delegate instance variable.
If the view controller chain is not broken, one possibility is to have the App Delegate send a "cleanUpNow" message to the top or root view controller, and have the view controllers pass that down the chain, with every view controller cleaning up as needed and then resending the message to all other controllers farther down the chain to clean up as well.
Reaching directly into another view controller is probably less clean that sending it a message to clean up itself (write to NSDefaults etc.). Of perhaps have them all message a central "clean up" controller object whose purpose is to gather all the necessary state and write it out in one coherent chunk.
If the chain is broken, another option is for the App Delegate to send a notification, with any controllers needed to clean up registering handlers for that "clean up" notification.
Upvotes: 0
Reputation: 5112
I would suggest you just register for some UIApplication notifications in your subclass and respond to them appropriately. Here is the link to the UIApplication docs. The notifications you can subscribe to are listed at the bottom of the page.
Here's an example of what you might do in your subclass:
[[NSNotificationCenter defaultCenter] addObserver:self
Selector:@selector(restore)
name:UIApplicationDidFinishLaunchingNotification
object :nil];
Don't forget to remove yourself as an observer as well. There are lots of tutorials online if you're not comfortable with NSNotifications.
Upvotes: 1
Reputation: 13204
As you mentioned above you have two options:
1-) Directly reach VC's UITextField
from AppDelegate
's applicationDidFinishLaunching
and applicationWillTerminate
methods.
On applicationDidFinishLaunching
:
Read from NSUserDefaults
, set UITextField
in VC.
On applicationWillTerminate
:
Read from UITextField
in VC, set NSUserDefaults
and synchronize
.
2) Create proper methods in VC to do the same job and call them from AppDelegate
.
-(void)record
{
// Read from UITextField, set UserDefaults and synchonize.
}
-(void)restore
{
// Read from UserDefaults, set UITextField.
}
Upvotes: 2