Using my application, the user will take a reading on my application, which will yield a string of text in this format: Reading, Date/Time, Gender, Age. Essentially, what I'm doing is taking this string and storing it in a table view in a different storyboard. Then, every time the application is closed and reopened, the saved values should remain. The action of saving the string should be triggered by pressing a save button. How can this be implemented? Sample code is appreciated.
The easiest solution is to use NSUserDefaults:
// Add a string & save permanently
NSMutableArray *savedStrings = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"SavedStrings"]];
NSString *sampleString = #"Reading, 4 Feb 2017, 12:00, male, 30 years";
[savedStrings addObject:sampleString];
[[NSUserDefaults standardUserDefaults] setObject:savedStrings forKey:#"SavedString"];
[[NSUserDefaults standardUserDefaults] synchronize];
// At launch, get saved strings - use to populate the tableview
NSMutableArray *savedStrings = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"SavedStrings"]];
I think this will help you...
//In firstViewController.m
// Create strings to store the text info
NSString *firstName = [self.firstNameTF text];
NSString *lastName = [self.lastNameTF text];
NSString *age = [self.ageTF text] ;
[defaults synchronize];
// Store the data with key.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:firstName forKey:#"firstName"];
[defaults setObject:lastName forKey:#"lastname"];
[defaults setObject:age forKey:#"age"];
//In requiredViewController.m write this code.
// Get the stored data before the view loads
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *firstName = [defaults objectForKey:#"firstName"];
NSString *lastName = [defaults objectForKey:#"lastname"];
NSString *ageString = [defaults objectForKey:#"age"];
// Set saved data in UIElements.
self.firstNameLabel.text = firstName;
self.lastNameLabel.text = lastName;
self.ageLabel.text = age;
Related
I am using NSUserDefaults to store my app settings/configuration.
The code responsible to saving defaults is below:
NSUserDefaults * standardUserDefaults = [NSUserDefaults standardUserDefaults];
// saving settings
[standardUserDefaults setObject:address.text forKey:#"URL"];
[standardUserDefaults setObject:username.text forKey:#"username"];
[standardUserDefaults setObject:password.text forKey:#"password"];
// synchronize the settings
[standardUserDefaults synchronize];
Indeed, the settings seem to have been saved. I open plist file from Libary/Preferences and see that the values are saved. I see those after my method is finished working and [even after] after closing the app.
My problem: whenever I start my app again, the saved values are gone from the plist file[the keys are still present], and I obviously cannot load my preferences.
Please advise.
You can use to save Settings:
NSMutableDictionary *dictSetting = [[NSMutableDictionary alloc] init];
[dictSetting setValue:address.text forKey:#"URL"];
[dictSetting setValue:username.text forKey:#"username"];
[dictSetting setValue:password.text forKey:#"password"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:dictSetting forKey:#"SETTINGS"];
[defaults synchronize];
to Retrive Setting:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *dictSettingData = [defaults objectForKey:#"SETTINGS"];
NSString *url = [dictSettingData valueForKey:#"URL"];
NSString *username = [dictSettingData valueForKey:#"username"];
NSString *password = [dictSettingData valueForKey:#"password"];
I keep posting about this same issue but I can't seem to get the answer and I've easily spent 30+ hours trying to figure it out. I will keep it as simple as possible. I have a dynamic tableview that adds custom cells when the "+" button is pressed. Each cell has 6 textFields. My problem now is that I save the textFields for one cell and it loads the same thing for every other cell. (by the way please just disregard the dynamic tableview reuse function)
Here is my code
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"expandingCell";
ExpandingCell *cell = (ExpandingCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ExpandingCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.autoresizingMask = UIViewAutoresizingFlexibleHeight;
cell.clipsToBounds = YES;
}
return cell;
}
Here is my code for the cells class: ExpandingCell.m
- (IBAction)Save:(id)sender
{
NSString *saveString = Date.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveString forKey:#"saveString"];
[defaults synchronize];
NSString *saveString1 = Course.text;
NSUserDefaults *defaults1 = [NSUserDefaults standardUserDefaults];
[defaults1 setObject:saveString1 forKey:#"saveString1"];
[defaults1 synchronize];
NSString *saveString2 = Score.text;
NSUserDefaults *defaults2 = [NSUserDefaults standardUserDefaults];
[defaults2 setObject:saveString2 forKey:#"saveString2"];
[defaults2 synchronize];
NSString *saveString3 = Par.text;
NSUserDefaults *defaults3 = [NSUserDefaults standardUserDefaults];
[defaults3 setObject:saveString3 forKey:#"saveString3"];
[defaults3 synchronize];
NSString *saveString4 = Putts.text;
NSUserDefaults *defaults4 = [NSUserDefaults standardUserDefaults];
[defaults4 setObject:saveString4 forKey:#"saveString4"];
[defaults4 synchronize];
NSString *saveString5 = GIR.text;
NSUserDefaults *defaults5 = [NSUserDefaults standardUserDefaults];
[defaults5 setObject:saveString5 forKey:#"saveString5"];
[defaults5 synchronize];
}
- (IBAction)Load:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *loadString = [defaults objectForKey:#"saveString"];
[Date setText:loadString];
[DateLabel setText:loadString];
NSUserDefaults *defaults1 = [NSUserDefaults standardUserDefaults];
NSString *loadString1 = [defaults1 objectForKey:#"saveString1"];
[Course setText:loadString1];
[CourseLabel setText:loadString1];
NSUserDefaults *defaults2 = [NSUserDefaults standardUserDefaults];
NSString *loadString2 = [defaults2 objectForKey:#"saveString2"];
[Score setText:loadString2];
NSUserDefaults *defaults3 = [NSUserDefaults standardUserDefaults];
NSString *loadString3 = [defaults3 objectForKey:#"saveString3"];
[Par setText:loadString3];
NSUserDefaults *defaults4 = [NSUserDefaults standardUserDefaults];
NSString *loadString4 = [defaults4 objectForKey:#"saveString4"];
[Putts setText:loadString4];
NSUserDefaults *defaults5 = [NSUserDefaults standardUserDefaults];
NSString *loadString5 = [defaults5 objectForKey:#"saveString5"];
[GIR setText:loadString5];
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
Please someone help its for a school project and I've desperately been trying to finish it before the deadline but I'm just totally lost on how to do this
In your ExpandingCell implement prepareForReuse method and clear the text fields.
Do the cells get reset immediately? Because if not, it seems like Zaph is correct that they all seem to be pointing to the same data. What you should do is create some kind of array or plist where you can store data for each cell rather than allocate and initialize data pointing to the same defaults. There is no way, afaik, that your cells can differentiate. Everytime you perform a load/save action, your data is written to the same place.
NSString *saveString = Date.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveString forKey:#"saveString"];
[defaults synchronize];
^ You overwrite the value for key saveString each time, thats why when it is reloaded, you load the saved value. What you can do is do something along the lines of:
[defaults setObject:saveString forKey:[NSString stringWithFormat:#"saveString%ld",(long)indexPath.row]];
This will ensure that a set of unique keys exist for each row, you can change out the row value for any other method of uniquely identifying a cell. perhaps you can try this:
[defaults setObject:saveString forKey:[NSString stringWithFormat:#"saveString1%#",nameOfGolfer]];
What would be better is to create an NSDictionary, and inserting an organized array of the date, course, putt # and all that jazz.
This way, each key for the NSDictionary would contain an array, and the key for each array would be a golfer name or course name or something. You just need to add one level higher of organizing your data and it will work.
EDIT1:
If you did that, then you would only have one object for the key saveString. A little noob to noob crashcourse of dictionaries and arrays. Basically NSUserDefault is really just an NSDictionary that can assign ONLY ONE (NS) object/value/number/anything to ONE key. A normal NSDictionary can not have objects as properties, but can have multiple values for ONE key. So you could add a NSString objet and then reference it with the key #"stringCatogory1", but there can only be one object for that key.
I think the NSUserDefaults is just a tool that Apple provided by combining an array and dictionary to let people make data persistent without creating their own custom framework for trying to save volatile data manually. You could basically just create a plist and manage it with an nsdictionary object everytime you wanted to change a value, essentially creating your own custom nsuserdefaults.
for example
[defaults setObject:firstName forKey:#"firstName"];
[defaults setObject:lastName forKey:#"lastname"];
[defaults synchronize]; //overwrites previous values saved from previous synch
So i would like to make a file called "SavedData.h" "SavedData.m" and store all my games saved data in these files...
How would I wire the whole process up to run in my "MainView.h" and "MainView.m"
I'm not that experienced with xcode...
The action in the MainView.m:
- (IBAction)btncheck:(id)sender {
if ([answer isEqualToString:#"Pizza Pie"]) {
//Name:Pizza Pie *SAVED
NSString *savestring = _textbox.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:savestring forKey:#"savedstring"];
[defaults synchronize];
}
_textbox is my textField
and in my SavedData.m:
//Name:Pizza Pie
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *loadstring = [defaults objectForKey:#"savedstring"];
[_textbox setText:loadstring];
}
How is this done?
& is it even possible?
I think you're aiming to save state to a file and restore it later (you wouldn't use source files for this, there's no compiler on the phone). Steps are:
Put whatever you want to save in a dictionary:
NSMutableDictionary *myState = [NSMutableDictionary dictionary];
myState[#"foo"] = #"bar";
Get a path to where you're app is allowed to save:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *pathFile = [paths[0] stringByAppendingPathComponent:#"mystate.plist"];
Save:
[myState writeToFile:pathFile atomically:YES];
Read it later:
myState = [[NSDictionary alloc] initWithContentsofFile:pathFile];
You can also build a mutable dictionary this same way (replace NSDictionary in the last line with NSMutableDictionary).
I have two completely separate tasks being carried out but somehow they seem to connect.
In ViewController 1, I have:
NSString *foo = #"foo";
NSUserDefaults *default1 = [NSUserDefaults standardUserDefaults]
[default1 setObject:foo forKey:#"foo"];
[default1 synchronize];
and when I do:
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"foo"]);
The value printed is what I expect it to be.
In ViewController 2, I have:
NSString *bar = #"bar";
NSUserDefaults *default2 = [NSUserDefaults standardUserDefaults]
[default2 setObject:bar forKey:#"bar"];
[default2 synchronize];
And same again when I NSLog it, the value is what I expect it to be.
But somehow when i try to print object #"foo" again it gives me the value for the second object, in this case #"bar"
Any guidance on why my original value is being overridden by the second value even tough the variable/key names are different in the 2 classes?
You are doing this for both:
[foo setObject:bar forKey:#"bar"];
Shouldn't it be:
[defaults1 setObject:foo forKey:#"foo"];
And
[defaults2 setObject:bar forKey:#"bar"];
There is however, a greater problem:
NSString *foo = #"foo";
NSUserDefaults *default1 = [NSUserDefaults standardUserDefaults];
[default1 setObject:foo forKey:#"foo"];
[default1 synchronize];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"foo"]);
NSString *bar = #"bar";
NSUserDefaults *default2 = [NSUserDefaults standardUserDefaults];
[default2 setObject:bar forKey:#"bar"];
[default2 synchronize];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"bar"]);
Will work properly, however you're creating defaults1 and defaults2 which are both instances of standard defaults, so:
NSUserDefaults * defaults1 = [NSUserDefaults standardUserDefaults];
NSUserDefaults * defaults2 = [NSUserDefaults standardUserDefaults];
[NSUserDefaults standardUserDefaults];
Are all pointers to the standardUserDefaults singleton. So they are identical instances. You could simply do:
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
NSString *foo = #"foo";
[standardDefaults setObject:foo forKey:#"foo"];
NSString *bar = #"bar";
[standardDefaults setObject:bar forKey:#"bar"];
[standardDefaults synchronize];
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"foo"]);
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"bar"]);
You can print out the entire set of user defaults with code like this
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *dictionary = [defaults dictionaryRepresentation];
NSLog( #"%#", dictionary );
Note that Apple puts lots of garbage in the user defaults, so you'll have to scroll to the end to see foo and bar. I'm guessing that you have a typo in code that you haven't shown us, and either foo is being overwritten, or foo simply isn't being displayed properly.
The current code in your question (after 1 edit) is all good and should work correctly.
I have two viewcontrollers. In my first viewcontroller:
{
NSString *string=textField.text;
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
[data setObject:string forKey:#"strings"];
[data synchronize];
}
How do I get the string value in my other viewcontroller?
Here you can use this in anyway in your application for store value of NSUserDefaults.
// --- Saving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSString
[prefs setObject:#"TextToSave" forKey:#"keyToLookupString"];
// saving an NSInteger
[prefs setInteger:42 forKey:#"integerKey"];
// saving a Double
[prefs setDouble:3.1415 forKey:#"doubleKey"];
// saving a Float
[prefs setFloat:1.2345678 forKey:#"floatKey"];
// This is suggested to synch prefs, but is not needed (I didn't put it in my tut)
[prefs synchronize];
Here you can use this in anyway in your application for get value of NSUserDefaults.
// --- Retrieving
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *myString = [prefs stringForKey:#"keyToLookupString"];
// getting an NSInteger
NSInteger myInt = [prefs integerForKey:#"integerKey"];
// getting an Float
float myFloat = [prefs floatForKey:#"floatKey"];
you can access NSUserDefaults in any controller (Any class of your application) of your application with the same code you have written in one class.
for getting the string value use the below code
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
NSString *myString = [data objectForKey:#"strings"];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
NSString *myString = [defaults stringForKey:#"strings"];
THis is the way to retrieve the data. Please note NSUserDefault is not used to pass data between two controllers. There are better methods for that.
Edit : After seeing Shaan Singh's comment
To pass data 2 view controllers you can declare a property in second view controller and access that from the present view controller.
It is already answered brilliantly here.
In the other ViewController,
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
NSString *string = [data objectForKey:#"strings"];
This will work because NSUserDefaults are a global key-value store that will persist across classes and applications.