saving checkmark accessory value in nsuserdefaults and then retreving them - iphone

hi
i am trying to save state of ticked row in nsuserdefaults.Some how i am getting error
:setObject undeclared.
my code is as:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
NSInteger newRow = [indexPath row];
NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
if(newRow != oldRow)
{
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
prefs = [setObject:lastIndexPath forKey:#"lastIndexPath"];
}
also i am trying to fetch row state in viewdidload method(should i fetch here?in view did load).my code is as:
- (void)viewDidLoad {
menuList=[[NSMutableArray alloc] initWithObjects:
[NSArray arrayWithObjects:#"LOCATION1",nil],
[NSArray arrayWithObjects:#"LOCATION2",nil],
[NSArray arrayWithObjects:#"LOCATION3",nil],
[NSArray arrayWithObjects:#"LOCATION4",nil],
[NSArray arrayWithObjects:#"LOCATION5",nil],
[NSArray arrayWithObjects:#"LOCATION6",nil],
[NSArray arrayWithObjects:#"LOCATION7",nil],
nil];
[self.navigationController setNavigationBarHidden:NO];
self.navigationController.navigationBar.tintColor=[UIColor blackColor];
self.navigationController.navigationBar.barStyle=UIBarStyleBlackTranslucent;
self.title=#"Location Selection";
[table reloadData];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if([[prefs objectForKey:#"lastIndexPath"] compare: indexPath]== NSOrderedSame){
cell.AccessoryType = UITableViewCellAccessoryCheckMark;
}
[super viewDidLoad];
}
and getting errors: indexPath Undeclared and cell undeclared.
i am getting why these errors are coming coz both of them(indexpath and cell) are not in scope,then where to place this code(nsuserdefaults data retriving code).Please guide my.
Thanks!

Try replacing this:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
prefs = [setObject:lastIndexPath forKey:#"lastIndexPath"];
With this:
[[NSUserDefaults standardUserDefaults] setObject:lastIndexPath forKey:#"lastIndexPath"];
Your error is because you are invoking setObject:forKey: without specifying that your prefs object is calling it. So the compilor is not identifying it as a valid message. You are also trying to assing that messages output to your prefs object, which is not correct.
This said, I am pretty sure you cant store an NSIndexPath inside of a plist directly, you would either have to store as an NSNumber, NSString, or NSData.
This would look like this:
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:lastIndexPath.row] forKey:#"lastIndexPath"];

Related

UITableView cell displays "null" value in index 0

I have textview in VC. Saving this textview using nsuserdefaults and get it later. In VC1 im getting saved textview and displaying in UITableView. But when i launch the app it automcatically displays "null" text in index 0.
VC:
-(void)save:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:textView.text forKey:#"savetext"];
[userData1 synchronize];
}
VC1:
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// textArray=[[NSMutableArray alloc]init];
txt=[[UITextView alloc]initWithFrame:CGRectMake(0, 0, 320, 400)];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *savedValue = [prefs stringForKey:#"savetext"];
NSLog(#"saved is %#",savedValue);
txt.text = [NSString stringWithFormat:#"%#", savedValue];
NSLog(#"text.txt is %#", txt.text);
MyAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if(![MyAppDelegate.textArray containsObject:txt.text]){
[MyAppDelegate.textArray addObject:txt.text];
}
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:MyAppDelegate.textArray forKey:#"save"];
[userData1 synchronize];
}
UITableView displays the text values using array:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"array is %#",myMutableArrayAgain);
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"mycell is %#",myMutableArrayAgain);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
NSLog(#"cell inside is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
This is all because the code is wrong at some places:
1) Nsmutable array with array is wrong:- as the userdefaults is returning you a single string.
So do it like this:-
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithObject:[userData1 valueForKey:#"savetext"]];
2) In VC you are saving the value for key in "savetext" but in VC1 you are retrieving the value as "save", so change it, it has been done in the above code.
// The above 2 points would solve your problem but I would say don't code like this as it would consume more memory and would remove tidyness of your code. The code which you have done can be done in a very efficient way.
I tell you .
// Take first View controller VC and add IBAction to a button and a textView or textField what ever.
Write this code in VC :-
.h file
#interface demoViewController : UIViewController{
IBOutlet UITextField *txt1;
}
-(IBAction)getData:(id)sender;
.m file
// first include header file of the next controller where you want to redirect suppose XYZ
#import XYZ.h
-(IBAction)getData:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:txt1.text forKey:#"savetext"];
demoViewController1 *demo=[[demoViewController1 alloc]initWithNibName:#"demoViewController1" bundle:nil];
[self.navigationController pushViewController:demo animated:NO];
}
// Take the second controller IN taht on ViewDisLoad or ViewDidAppear whatever you feel like
// Take a global MuttableArray
NSMutableArray *myMutableArrayAgain;
// I write this code on ViewDidload allocate the array here as MutableObject need to be allocated
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
myMutableArrayAgain=[[NSMutableArray alloc]init];
[myMutableArrayAgain addObject: [userData1 valueForKey:#"savetext"]];
// Now table View Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
NSLog(#"cell inside is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
// Apply this way you can do the stuff in less code and in a great way.

NSRangeException Error with NSArray - While setting image view in another ViewController

I'm getting an image from the AppDelegate, then setting it to the ViewController's table.imageView property. It's throwing me an NSRangeException:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (2) beyond bounds (2)'
I made sure my array and rows are counted by [array count]. Very confused. Here's the code:
#pragma mark - viewWillAppear
- (void)viewWillAppear:(BOOL)animated {
PBAppDelegate *dataObject = (PBAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *titleRead = dataObject.title;
NSString *descRead = dataObject.desc;
UIImage *imageRead = dataObject.image;
if ([titleRead isEqualToString:#"" ] || [descRead isEqualToString:#""]) {
// it's nil
} else {
if (titleRead) {
[data addObject:[NSArray arrayWithObjects:titleRead, descRead, imageRead, nil]];
dataObject.title = #"";
dataObject.desc = #"";
[tableView reloadData];
}
NSUserDefaults *dataDefaults = [NSUserDefaults standardUserDefaults];
[dataDefaults setObject:[NSArray arrayWithArray:data] forKey:#"dataArrayKey"];
[dataDefaults synchronize];
}
}
#pragma mark - viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
data = [[NSMutableArray alloc] init];
self.data = [[NSUserDefaults standardUserDefaults] objectForKey:#"dataArrayKey"];
[tableView reloadData];
}
#pragma mark - Table Datasource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [[data objectAtIndex:indexPath.row] objectAtIndex:0];
cell.detailTextLabel.text = [[data objectAtIndex:indexPath.row] objectAtIndex:1];
cell.imageView.image = [UIImage imageNamed:[[data objectAtIndex:indexPath.row] objectAtIndex:2]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
It's probably this line:
cell.imageView.image = [UIImage imageNamed:[[data objectAtIndex:indexPath.row] objectAtIndex:2]];
The console output says there are 2 elements in the array. Elements start at 0; so you can access objectAtIndex:0 and objectAtIndex:1. Two would be the 3rd element of the array, and is out of bounds.
Sorry if that's all obvious, just taking a quick stab... Enjoy. :)
EDIT
Actually, the issue could be that imageRead is nil when you add it to the array. That would cause the array to have only 2 elements in it. You may check for that, and/or use [NSNull null] if you don't have an image...
Make sure the array actually has 3 elements by doing something like this:
NSArray *array = [data objectAtIndex:indexPath.row];
if ([array count] > 2)
{
cell.imageView.image = [UIImage imageNamed:[array objectAtIndex:2]];
}

Xcode: saving data issue with NSUserDefaults and TableView

I am trying to save data via NSUserDefaults and view it on the tableView but nothing happen after I click on the save button, after I stop and run the application again the data that I saved it I can see it which every time it overwrite on the old data. Am I doing something wrong? Or should I use something different from NSUserDefaults?
Thanks in advance.
-(IBAction)save{
NSUserDefaults *add1 = [NSUserDefaults standardUserDefaults];
[add1 setObject:txt1.text forKey:#"txt1"];
[add1 synchronize];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
self.dataArray = [NSArray arrayWithObjects:[prefs objectForKey:#"txt1"], nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *string = [dataArray objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text=string;
return cell;
}
There are two issues in your code:
You are not refreshing the tableview. You can do this by calling:
[self.tableView reloadData]; // Or whatever property is pointing to your tableview
Every time you save a value, you save it under the same key (txt1) and that's why you override every time. If you want a list of items (an array) and to append the item into this array, you could do something like this:
NSMutableArray *myList = [[[NSUserDefaults standardUserDefaults] valueForKey:#"myTxtList"] mutableCopy];
[myList addObject:txt1.text];
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:myList] forKey:#"myTxtList"];
[add1 synchronize];
self.dataArray = myList;
[self.tableView reloadData];
P.S. Of course you need to set your dataArray accordingly in your viewDidLoad:
self.dataArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"myTxtList"];
As A for Alpha said try that & in addition I am having doubt in your save method definition too. Just try changing it to the following
-(IBAction)save:(id)sender{
NSUserDefaults *add1 = [NSUserDefaults standardUserDefaults];
[add1 setObject:txt1.text forKey:#"txt1"];
[add1 synchronize];
[tableView reloadData];
}
This may work out for u.
I guess you need to call [yourTableView reloadData] after saving the data in userDefaults. This should solve your problem.

Remove object of NSUserDefault by tableview cell

I have a list of favorites that are stored in the NSUserDefaults, single favorited are stored by NSDictionary:
NSUserDefaults *userPref = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *bookmark = [NSMutableDictionary new];
[bookmark setValue:author.text forKey:#"author"];
[bookmark setValue:book.text forKey:#"book"];
[bookmarks addObject:bookmark];
[userPref setObject:bookmarks forKey:#"bookmarks"];
[userPref synchronize];
Everything is ok, but now I want to delete a single favorite with the swipe of a cell. I have add the method for show the the delete swipe but I do not know how to remove the single bookmark from nsuserdefaults.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
[self.listBookamrks removeObjectAtIndex:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
NSUserDefaults *userPref = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *storedBookMark = [[userPref ObjectForKey:#"bookmarks"]mutable copy];
// If you want to remove an object from the dictionary
[storedBookMark removeObjectForKey:#"Your KEy"];
// if you want to empty the dictionary
[storedBookMark removeAllObjects];
[userPref setObject: storedBookMark forKey:#"bookmarks"];
[userPref synchronize];
// if you want to store nil // go back to default state ..
[userPref setNilValueForKey:#"bookmarks];

Save checkmarked row into appsettings. EDITED

EDIT: I got a saving and now It do not work.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:countries forKey:#"country"];
[defaults synchronize];
Saving.
But I think I must load the arrays from the appsettings. how?
Got this now:
countries = [[NSArray alloc] initWithObjects:#"All",#"Austria",#"Belarus",#"Canada",#"Czech Republic",#"Denmark",#"Germany",#"Finland",#"France",#"Latvia",#"Norway",#"Russia",#"Slovakia",#"Slovenia",#"Switzerland",#"Sweden", #"USA", nil];
Use synchronize mathod of NSUserDefault.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int newRow = [indexPath row];
int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
if (newRow != oldRow)
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:
indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:
lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
NSUInteger row = [indexPath row];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//Suppose you have used **myArrayUsedInTableView** Array to construct TableView
..................................................................................
............./*Do changes here in myArrayUsedInTableView as per your requirement*/
....................................................................................
//Now store your array myArrayUsedInTableView in NSUserDefault
[defaults setObject:myArrayUsedInTableView forKey:#"StoredArray"];
[defaults synchronize];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}