Save and Load Data on Today Extensions (iOS 8) - ios

Is it possible to save and load data on Today Extension using NSUserDefaults?
After closing the Notification Center, the widget behaves like an app which is terminated, so any data results lost. How could I solve this issue?
This is my code:
NSUserDefaults *defaults;
- (void)viewDidLoad {
[super viewDidLoad];
defaults = [NSUserDefaults standardUserDefaults];
NSArray *loadStrings = [defaults stringArrayForKey:#"savedStrings"];
if ([loadStrings objectAtIndex:0] != nil) {
[display setText:[NSString stringWithFormat:#"%#", [loadStrings objectAtIndex:0]]];
}
if ([loadStrings objectAtIndex:1] != nil) {
calculatorMemory = [NSString stringWithFormat:#"%#", [loadStrings objectAtIndex:1]].doubleValue;
}
}
- (IBAction)saveData:(id)sender {
NSString *displayString;
NSString *memoryString;
NSArray *saveStrings = [[NSArray alloc] initWithObjects: displayString, memoryString, nil];
defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveStrings forKey:#"savedStrings"];
[defaults synchronize];
}

You need to use app group identifier instead of com.*
For instance:
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.company.appgroup"];
Don't forget to synchronise when you store data
[shared synchronize];

You need to add the App Group stuff detailed under here and then if it actually worked (pretty iffy under beta) it should allow you to share NSUserDefault data like normal between the host and widget.
Edit: Normal NSUserDefaults does not work. Apple has implemented a new method. To use, simply redefine your NSUserDefaults instance like this:
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"com.you.app.container"];

For anyone wondering how in the world do you save and get values then look at this code.
In your regular app add this to save whatever you like in your *.m file.
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.yourcompanyname.TodayExtensionSharingDefaults"];
//save dic
[shared setObject:dictionary2 forKey:#"dicForTodayWidget"];
//save array
[shared setObject:tempArray2 forKey:#"arrayForTodayWidget"];
//save some value
[shared setObject:#"1234" forKey:#"myValForTodayWidget"];
[shared synchronize];
In your today widget under TodayViewController.m in viewDidLoad add this.
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.yourcompanyname.TodayExtensionSharingDefaults"];
//get dic
NSMutableDictionary *dictionary = [shared objectForKey:#"dicForTodayWidget"];

You first need the App Groups set up for both targets (application and the extension).
Then, use the
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.company.myapp"];
to obtain the defaults object which you can read from/write to as usual.
If you want to be notified of changes to the defaults, use the NSUserDefaultsDidChangeNotification in your widget (or app).
For a step-by-step tutorial explaining all this, take a look at this blog post.

#edukulele
Today Extension and Main app run on two processes. Today Extension can't receive NSUserDefaultsDidChangeNotifications. I tried use MMWormhole. It is very good.

Related

How to remove data after share between extension and host app in iOS

I have an iOS app, need to handle user share data from third app.
To handle this, I cache the data by UserDefaults in extension module:
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.app.share"];
// write data
[userDefaults setValue:[((NSURL*) item) absoluteString] forKey:#"shareData"];
//open app
[self openApp];
After that, app is opened and then can read and handle the data:
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.app.share"];
//read data
NSString *data = [userDefaults valueForKey:#"shareData"];
NSLog(#"%#", data);
Till now, everything is ok. App host can get the share data from extension correctly.
However, when I need to remove the data after handling:
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.app.share"];
//read data
NSString *data = [userDefaults valueForKey:#"shareData"];
NSLog(#"%#", data);
...use the data and then remove it
[userDefaults removeObjectForKey: #"shareData"]
Then strange thing happens as following steps:
share data from third app.
if app no running , then after open, data is nil.
if app is running, then the app switch to get the data correctly.
That is to say, the data is missing during app launching.
What's the reason then?
Find a way. Add a timer or delay, when time is out, remove the key in extension module. It works.
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.app.share"];
//write data
[userDefaults setObject:[((NSURL*) item) absoluteString] forKey:#"shareData"];
[self openApp];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[userDefaults removeObjectForKey:#"shareData"];
});

How to save user's input in UITextField?

I wanted to know how can I save a user's input when the user enters something from his mobile phone in the UITextField?
If I just use the text field and run the app I can enter data in the text field but when I close the application the data is gone. So how can I store that data permanently and show it again after the application is closed and reopened. Is there any way to save it?
At first, you should save the text when user did editing before user close the application(e.g. saved by NSUserDefaults):
self.yourTextView.delegate = self;
- (void)textViewDidChange:(UITextView *)textView
{
if (textView.markedTextRange == nil)
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:textView.text forKey:#"userText"];
[defaults synchronize];
}
}
Then, load the text that user saved before when user open your application again:
- (void)viewDidLoad
{
[super viewDidLoad];
self.yourTextView.text = [[NSUserDefaults standardUserDefaults]objectForKey:#"userText"];
}
We can save data into 3 data base
If you want to store single data into db, you can use
NSUserDefault
For store
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:textView.text forKey:#"textviewdata"];
[defaults synchronize];
For Retrieve
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *strTextViewText = [NSString stringWithFormat:#"%#",[defaults objectForKey:#"textviewdata"]];
Then Store a larger amount of data,we can use
SQLite
CoreData
Here are some ways to save data inside application.
create local database using sqlite or coredata both provides facilty to save data locally and before use please find the different situations to use these databases.
using NSUserDefaluts but not recomemded because NSUserDefaults aren’t meant to store sensitive information for more information see imp link see example also if you still.
To store data using NSUserDefaluts:
[[NSUserDefaults standardUserDefaults]setObject:self.textfield.text forKey:#"yourKey"];
To get data anywhere inside app:
object = [[NSUserDefaults standardUserDefaults] valueForKey:#"yourKey"];
Try with this:
-(void)viewDidDisappear:(BOOL)animated
{
[[NSUserDefaults standardUserDefaults]setObject:self.urtextfield.text forKey:#"savedtext"];
}
-(void)viewWillAppear:(BOOL)animated
{
self.urtextfield.text = [[NSUserDefaults standardUserDefaults]objectForKey:#"savedtext"];
}

Intermittently Calling [NSUserDefaults synchronize] Returns Success but isn't shown during ObjectForKey

I have 2 applications sharing data via the NSUserDefaults, initWithSuite ID. Using iOS Dev Center.
One in 2 attempts the following code block apparently fails to write my dictionary object to the shared UserDefault area, I use the BOOL response from Synchronise to check the success. eg, (4 NSData objects, one, or more, or all of the items might fail to write to storage).
I use [[NSUUID uuid] UUIDString] as a key [EDIT: Been told in comments that this changes value?, Tried a Static String same result, 25% fail rate]
Any help will be greatly received.
Writer - Application 1
NSUserDefaults *myDefaults = [[NSUserDefaults alloc]
initWithSuiteName:FRGFileShareID];
NSString *uuid = [[NSUUID UUID] UUIDString];
[myDefaults setObject:**customObjectDict** forKey:uuid];
BOOL successSave = [myDefaults synchronize];
if (!successSave) {
DLog(#"Failed To Save To Defaults");
}
Reader - Application 2
NSUserDefaults *myDefaults = [[NSUserDefaults alloc] initWithSuiteName:FRGFileShareID];
if ([myDefaults objectForKey:uuid]) {
[mediaArray addObject:[myDefaults objectForKey:uuid]];
[myDefaults removeObjectForKey:uuid];
}
If i log out [[myDefaults dictionaryRepresentation] allKeys] im lucky if any of my keys are there.
Again with this working 75% of the time, im not sure whats causing the intermittency but its killing the usability of my feature.
You have not pass the value to NSUserDefault, change the code like this,
[myDefaults setObject:uuid forKey:"myDict Object"];
[myDefaults synchronize];

defaultPrefs not updating

I have created a Prefs Controller class, which dose what it says controlls my prefs values. I have two specific values in my prefs both strings one that's called installSelected and the other called finishSelected, I setting them as a string that's either T or F...
When the app first starts I create the new prefs and the values are set to F automatically as those are their default values in the plist bundle. Then later in the app I overwrite installSelected to T. When I restart the application it returns the correct value as T. Then I write over it again using F. Again I restart but when I read the values this time it still shows T when it should be F.
I have debugged this and I am just not sure why it's not saving the value.
This is what my prefController method looks like that is used to write the new values:
- (void) writeBool:(NSString *)name MyBool:(NSString *)myboolString {
prefs = [NSUserDefaults standardUserDefaults];
if ([name isEqualToString:#"InstallsSelected"]) {
[prefs setObject:myboolString forKey:name];
}
else if ([name isEqualToString:#"FinishSelected"]) {
[prefs setObject:myboolString forKey:name];
}
[prefs synchronize];
}
I call the above method like this
[prefsController writeBool:#"InstallsSelected" MyBool:#"F"];
It just makes no sense that it's not working as I am able to change it from F to T but not back if needed and none of the code is different. What might be causing this problem?
Why are you using strings instead of bool values?
You have to set your boolean by using:
// Notice setBool
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"pref"];
and call synchronize after it:
[[NSUserDefaults standardUserDefaults] synchronize];
To retrieve the value, you call:
// Notice boolForKey
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"pref"]) {
// False
} else {
// True
}
To register default prefs, use:
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], #"pref1",
[NSNumber numberWithBool:YES], #"pref2",
nil];
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
[prefs registerDefaults:appDefaults];
Are you on the simulator or a real device? I have had serious problems getting the sync right in the Simulator. It turns out that if you just do a rebuild from xCode, the user preferences are not saved. They are saved if you bring the app to the background in the Simulator (press cmd-shift-H).
Also it helps to NSLog as much as possible to see what is written in the prefs.

How to make the save data appear when loading view controller?

The following code is saving data and loading, but it doesn't show the data when loading view controller.It just says label (Xcode default uilabel).
I believe that I have to use synchronize ,but I am not too sure. May someone help me out.
Implementation file:
- (IBAction)minus
{
mini = mini - 1;
minus.text = [NSString stringWithFormat:#"%i", mini];
[[NSUserDefaults standardUserDefaults] setInteger:mini forKey:#"M"];
}
- (void)viewDidLoad
{
mini = [[NSUserDefaults standardUserDefaults] integerForKey:#"M"];
}
Header file:
IBOutlet UILabel *minus;
Change:
[[NSUserDefaults standardUserDefaults]setInteger:mini forKey:#"M"];
Into:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setInteger:mini forKey:#"M"];
[prefs synchronize];
And it should work.
And i dont see you setting minus.text in viewdidload.
As H2CO3 says, you need to end the save process with
[prefs synchronize];
Why don't you open the iPhone Simulator folder to see if a plist file has been created inside Library > Preferences?

Resources