Wrong Cell Selected in CutomTableViewCell - iphone

In multiple selection of tableview cell. When I select 1st cell 7th cell is also automatically get selected. I've implemented multiple cell selection functionality. I tried some methods but ain't working.
This is my code, what am I doing wrong?
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
[mytableview deselectRowAtIndexPath:indexPath animated:YES];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[def setObject:[model objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"model_%i",counter]];
[def setObject:[year objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"year_%i",counter]];
[def setObject:[colorid objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"colorid_%i",counter]];
[def setObject:[vin objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"vin_%i",counter]];
[def setObject:[price objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"price_%i",counter]];
[def setObject:[color objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"color_%i",counter]];
counter++;
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[selectedIndexes addObject:[NSNumber numberWithInt:indexPath.row]];
[selectedIndexes insertObject:[NSNumber numberWithInt:indexPath.row] atIndex:counter];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[selectedIndexes removeObject:[NSNumber numberWithInt:indexPath.row]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"model_%i",counter]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"year_%i",counter]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"colorid_%i",counter]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"vin_%i",counter]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"price_%i",counter]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:#"color_%i",counter]];
counter--;
}
I am using custom tableview cell, I've checked its height also. My cellforRowAtIndexPath method looks like,
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"CustomCell17";
VehicleListCell *cell = (VehicleListCell *)[mytableview dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"VehicleListView" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
return cell;
}

[selectedIndexes addObject:[NSNumber numberWithInt:indexPath.row]];
[selectedIndexes insertObject:[NSNumber numberWithInt:indexPath.row] atIndex:counter];
Here you add the same object twice. That might cause your issue.
Log selectedIndexes to see what is happening.

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.

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

UITableView Checkmark Only Select One

I am using the code below to set a UITableViewCell's accessory to a checkmark and then write to NSUserDefaults. However it doesn't seem to be working properly. The NSUserDefault never seems to be set. If you can see the problem please point it out.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *text = [array objectAtIndex:indexPath.row];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
if ([text isEqualToString:[NSString stringWithFormat:#"%i", k10]]) {
[defaults setInteger:k10 forKey:kNumberOfChartsToDownload];
} else if ([text isEqualToString:[NSString stringWithFormat:#"%i", k25]]) {
[defaults setInteger:k25 forKey:kNumberOfChartsToDownload];
} else if ([text isEqualToString:[NSString stringWithFormat:#"%i", k50]]) {
[defaults setInteger:k50 forKey:kNumberOfChartsToDownload];
} else if ([text isEqualToString:[NSString stringWithFormat:#"%i", k75]]) {
[defaults setInteger:k75 forKey:kNumberOfChartsToDownload];
} else if ([text isEqualToString:[NSString stringWithFormat:#"%i", k100]]) {
[defaults setInteger:k100 forKey:kNumberOfChartsToDownload];
}
}
[self.navigationController popViewControllerAnimated:YES];
}
else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
}
I am also NSLogging the NSUserDefault when the application launches. However the integer is allways 100. Please do the same if you can see the problem.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (! [defaults objectForKey:#"firstRun"]) {
[defaults setObject:[NSDate date] forKey:#"firstRun"];
}
NSInteger daysSinceInstall = [[NSDate date] timeIntervalSinceDate:[defaults objectForKey:#"firstRun"]] / 86400;
if (! [defaults objectForKey:#"first"]) {
[defaults setObject:[NSDate date] forKey:#"first"];
}
if (daysSinceInstall == 0 && [defaults boolForKey:#"askedForSettings"] == NO) {
if (![defaults integerForKey:kNumberOfChartsToDownload]) {
NSLog(#"no defaults");
[defaults setInteger:k25 forKey:kNumberOfChartsToDownload];
} else if ([defaults integerForKey:kNumberOfChartsToDownload]) {
NSLog(#"%i", [defaults integerForKey:kNumberOfChartsToDownload]);
}
[defaults setBool:YES forKey:#"askedForSettings"];
}
By default, NSUserDefaults saves just before the application is unloaded from memory. A problem I have encountered, is that if you quit your application from Xcode, various cleanup methods are never called. Add [[NSUserDefaults standardUserDefaults] synchronize]; to your code after you are done saving the objects in the defaults. This should force NSUserDefaults to save any unsaved changes at that time.

Read/Unread cell (using drawrect)

My app downloading posts from internet to UITableViewCell. When user taps on cell, i am need to set this article as read (like on Mail.app). I dont know how to do that.
I am adding url (when user press cell) to database (like "url|url|url"), open detail view. And when he goes back to UITableView checking existing url in DB. Table now is too slow!
Can u help me and say what other method i can use to do that? Like in mail.app. I am using custom cell and code in drawRect method. Please, help
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%d",indexPath.row];
NSMutableArray *array=[NSMutableArray array];
if([[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]!=nil)
[array addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]];
NSUInteger indexOfObject = [array count]>0?[array indexOfObject:[NSNumber numberWithInt:indexPath.row]]:100000; //I add this, because row don't want update using updateRowAtIndexPath
QuickCell *cell = (QuickCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil || (indexOfObject!=NSNotFound && indexOfObject!=100000))
{
cell = [[[QuickCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.frame = CGRectMake(0.0, 0.0, 320.0, 68.0);
cell.accessoryType = UITableViewCellAccessoryNone;
if([self.subject count]>0)
{
[self.allImages addObject:[NSNull null]];
NSString *userNameLJ = [NSString stringWithFormat:#"%#",[self.journalurl objectAtIndex:indexPath.row]];
userNameLJ = [userNameLJ stringByReplacingOccurrencesOfString:#"http://"
withString:#""];
userNameLJ = [userNameLJ stringByReplacingOccurrencesOfString:#".livejournal.com"
withString:#""];
userNameLJ = [userNameLJ stringByReplacingOccurrencesOfString:#"community/"
withString:#""];
NSString *postURL = [NSString stringWithFormat:#"http://m.livejournal.com/read/user/%#/%#",userNameLJ,[self.ditemid objectAtIndex:indexPath.row]];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[self.subject objectAtIndex:indexPath.row] forKey:#"title"];
[dict setObject:[Utilities replaceForCell:[Utilities flattenHTML:[self.entry objectAtIndex:indexPath.row]]] forKey:#"description"];
if([[database executeQuery:#"SELECT * FROM read WHERE posts=?;",postURL] count]>0)
{
//if this post is read
[dict setObject:[NSNumber numberWithBool:NO] forKey:#"highlighted"];
}
else {
[dict setObject:[NSNumber numberWithBool:YES] forKey:#"highlighted"];
}
[dict setObject:[self.journalname objectAtIndex:indexPath.row] forKey:#"nick"];
[cell setContentForCell:dict];
BOOL trueOrFalse = [[self.allImages objectAtIndex:indexPath.row] isKindOfClass:[NSNull class]]?YES:NO;
if(trueOrFalse)
{
if (tableView.dragging == NO && tableView.decelerating == NO)
{
//if no image cached now, download it
if(indexPath.row<6 && self.updating==YES)
[self startDownloading:indexPath];
if(self.updating==NO)
[self startDownloading:indexPath];
}
}
else
{
[cell setImageForCell:[self.allImages objectAtIndex:indexPath.row]];
}
}
if(indexOfObject!=NSNotFound && indexOfObject!=100000)
{
//delete this row from userdefaults
[array removeObjectAtIndex:indexOfObject];
if([array count]>0)
[[NSUserDefaults standardUserDefaults] setObject:array forKey:#"readPostS"];
else [[NSUserDefaults standardUserDefaults] removeObjectForKey:#"readPostS"];
}
}
return cell;
}
//////////////////////////////////////////////////////////////
///////-(void)viewWillApear
//////////////////////////////////////////////////////////////
NSMutableArray *readPosts = [NSMutableArray array];
if([[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]!=nil)
{
[readPosts addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]];
self.read = (NSMutableArray*)[database executeQuery:#"SELECT * FROM read;"];
for(int i=0;i<[readPosts count];i++)
{
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[[readPosts objectAtIndex:i] intValue] inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
}
///////////////////////////////////////////////
///////THIS FILE OPENS POSTS FOR READING
///////////////////////////////////////////////
if([[database executeQuery:#"SELECT * FROM read WHERE posts=?;",self.postURL] count]==0)
{
[database executeNonQuery:#"INSERT INTO read VALUES (?);",self.postURL];
NSMutableArray *defaults = [NSMutableArray array];
if([[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]!=nil)
defaults = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"readPostS"]];
[defaults addObject:[NSNumber numberWithInt:self.currentIndex]];
[[NSUserDefaults standardUserDefaults] setObject:defaults forKey:#"readPostS"];
}
Ok. I think, my code is to bad and u can understand, what i am doing here) Answer on other question. How i can update hidden cells? User see only 6 cell in a moment, i need to update, for example, 10 cells. How?
Or, how reload cell, if it allready exists? Lets say -
NSString *CellIdentifier = [NSString stringWithFormat:#"%d",indexPath.row];
QuickCell *cell = (QuickCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[QuickCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.frame = CGRectMake(0.0, 0.0, 320.0, 68.0);
cell.accessoryType = UITableViewCellAccessoryNone;
.........}
now cell exists and if i call reload data nothing happen. And reloadCellAtIndexPath does not working too, because cell has unique identifier and ixists.
HOW I CAN RELOAD CELL AND CALL DRAWRECT AGAIN?))
You can implement this functionality by adding your code in the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//Add the indexPath.row values in an array.
}
Add the custom functionality (like showing Title in BOLD for unread) in the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Check if the indexPath.row is available in the array
//If yes then Normalize the fonts
//Else Keep them BOLD.
}
Unless you're really doing some drawing, don't implement in drawRect:. I don't know you're specific code, so that may not be correct in your case.
To reload the entire table (all cells), look at UITableView's - (void)reloadData
To reload a specific cell, look at UITableView's - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation and use it to reload the cell in question.

iPhone, how can I store / load one value on a simple table view settings screen?

Heres my cellForRowAtIndexPath where I've loading a value for a row, instead of a value from a simple array and converting it to a row.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier] autorelease];
}
NSInteger row = [indexPath row];
cell.textLabel.text = [dayArray objectAtIndex:row];
NSUserDefaults *myDefaults = [NSUserDefaults standardUserDefaults];
NSInteger startRow = [myDefaults integerForKey:kStartRow];
if (startRow == row) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Heres where I'm saving the value, notice I'm using kStartRow and the array value each time.
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int newRow = [indexPath row];
NSUserDefaults *myDefaults = [NSUserDefaults standardUserDefaults];
[myDefaults setInteger:newRow forKey:kStartRow]; // Set the tablecell
[myDefaults setObject:[dayArray objectAtIndex:newRow] forKey:kNSUEndOfMonthDay];
[myDefaults synchronize];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadData];
[self.navigationController popViewControllerAnimated:YES];
}
Using two values makes is a bit messy now when I want to set a default when the app first runs. How can I manage with one stored value ?
cell.accessoryType = indexPath.row == [dayArray indexOfObject:[[NSUserDefaults standardUserDefaults] objectForKey:kNSUEndOfMonthDay]] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
?