UITableView cell displays "null" value in index 0 - iphone

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.

Related

UITableViewCell returns null using objectForKey

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"];
txt.text = [NSString stringWithFormat:#"%#", savedValue];
MyAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// [MyAppDelegate.textArray addObject:txt.text];
if(![MyAppDelegate.textArray containsObject:txt.text]){
[MyAppDelegate.textArray addObject:txt.text];
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:MyAppDelegate.textArray forKey:#"save"];
[userData1 synchronize];
}
[self.view addSubview:txt];
tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) style:UITableViewStylePlain];
NSLog(#"Scrolling");
tableView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleRightMargin;
// tableView.contentInset = UIEdgeInsetsMake(0, 0,300, 0); //values passed are - top, left, bottom, right
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
tableView.contentInset = UIEdgeInsetsMake(0, 0,300, 0);
//self.view = tableView;
[self.view addSubview:tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"count is %#",myMutableArrayAgain);
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier ];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
NSLog(#"cell 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;
}
I had this problem too. NSUserDefaults can't process with mutable objects.
Try to store your string into CoreData. Is it simple and powerful. I make it and it works perfect.
If you have not skills with CoreData here is tutorial:
http://www.youtube.com/watch?v=StMBHzA7h18
Step1 create new file - Data model
Step2 create Entity (name) there add one atribute (name2)
So simple!

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]];
}

Model View Controller with UITextFieldDelegate issue

I'm working with something really easy, and I think I'm making a small mistake that I'm probably just not seeing here. I have this going on between my MVC to simply transfer a name from the AddViewController to the MasterViewController, and add it to the MasterController's UITableView. Although, I have "NSLogged" everything down to each step of the process, and what I'm basically getting out of it is that the text that's inputted into the "name" UITextField isn't passing itself into my NSString method, _aname.
Also, at one point, this was working and I was having trouble with setting the name to the MasterViewController from the AddViewController. So, if anyone could just give that part a look over too and make sure I have everything set up properly, I would hugely appreciate it.
In a nutshell, it looks like this.
MasterViewController.h
#property (nonatomic, strong) AddViewController *addViewController;
MasterViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [self.Name setName:name];
NSLog(#"%#", cell.textLabel.text);
return cell;
Name.h
- (NSString *)setName:(NSString *)name;
Name.m
- (NSString *)setName:(NSString *)name
{
[_nameStack addObject:name];
NSLog(#"Name set to: %#", name);
return name;
}
AddViewController.m
- (void)viewDidLoad
{
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(finalizeAdditionOfName:)];
NSUserDefaults *nameDefault = [NSUserDefaults standardUserDefaults];
nameInput.text = [nameDefault objectForKey:#"Name"];
}
- (IBAction)finalizeAdditionOfName:(id)sender
{
_name = [[Name alloc] init]
nameInput.text = _name;
[_name setName:_aname];
NSLog(#"Name set to (AddViewController): %#", _aname);
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath section] == 0) { // Section 1
if ([indexPath row] == 0) {
nameInput.delegate = self;
[nameInput setEnabled: YES];
[cell addSubview:nameInput];
[nameInput becomeFirstResponder]
nameInput.text = _aname;
NSUserDefaults *nameDefault = [NSUserDefaults standardUserDefaults];
[nameDefault setObject:_aname forKey:#"Name"];
}
}
if my comment doesn't turn out to be helpful, I made a sample project that I think shows how you might get the data from the text field to the table view. Tell me if you have any questions about it:
https://github.com/MaxGabriel/TextField-TableView-Example

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.

saving checkmark accessory value in nsuserdefaults and then retreving them

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"];