I have table view that rendering cells. I created the cell once and reuse it. In each cell there is a button to do vote action for a place. On the vote action I want to change the background image of the button. When I click on the button in a certain cell the background image changes, but when I scroll down I find another button with the changed background image. I believe that the problem is because I'm using dequeueReusableCellWithIdentifier but I can't find a way to solve this problem.
Here is my code:
// .h file
#interface VotePlaceView : UIView < UITableViewDataSource, UITableViewDelegate>
{
VotePlaceView *votePlaceCell;
}
and in the implementation file
// .m File
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"votePlaceCell"];
if (cell)
{
votePlaceCell = (VotePlaceView*)[cell viewWithTag:10];
}
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"votePlaceCell"];
//GlobalObjects is a customised thing for me to load the cell in different languages
votePlaceCell = [[GlobalObjects loadNibNamed:#"votePlaceCell" owner:self options:nil] objectAtIndex:0];
votePlaceCell.tag = 10;
[cell addSubview:votePlaceCell];
}
.
. //Fill data in the cell
.
//This gives different IDs, no ID like the others (unique ID)
NSLog(#"ID %d", [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue]);
UIButton* voteButton = (UIButton*)[votePlaceCell viewWithTag:20];
voteButton.tag = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
return cell;
}
-(IBAction)votePlace:(UIButton *)sender
{
// I tried two ways to achieve my point with no luck
//Selected case give the new background image
//THE FIRST WAY
sender.selected = YES;
//OR THE SECOND WAY
UIButton* newVotePlace;
newVotePlace = (UIButton*)[[sender superview] viewWithTag:sender.tag];
newVotePlace.selected = YES;
}
Any idea?
The Solution
#Akhilrajtr's answer solved my problem, after I made some changes to his answer. Here is the solution, in case if anyone faced the same problem.
Instead of using a UIButton, I used UIButton and UIImageView. I put the UIImageView behind the UIButton and I give the UIImageView two images in the default case and in the highlighted case. I cleared the background image of the UIButton and then followed the accepted answer as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.
.
int placeId = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
UIButton* voteButton = (UIButton*)[votePlaceCell viewWithTag:20];
if (!voteButton) {
voteButton = (UIButton*)[votePlaceCell viewWithTag:placeId];
}
voteButton.tag = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
if ([selectedIdArray containsObject:[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"]]) {
UIImageView* voteImage;
voteImage = (UIImageView*)[votePlaceCell viewWithTag:11];
voteImage.highlighted = YES;
} else {
UIImageView* voteImage;
voteImage = (UIImageView*)[votePlaceCell viewWithTag:11];
voteImage.highlighted = NO;
voteButton.selected = NO;
}
return cell;
}
-(IBAction)votePlace:(UIButton *)sender
{
[selectedIdArray addObject:[NSNumber numberWithInt:sender.tag]];
UIImageView* voteImage;
voteImage = (UIImageView*)[[sender superview] viewWithTag:11];
voteImage.highlighted = YES;
}
Try this,
Create a NSMutableArray *selectedIdArray (don't forget to instatiate selectedIdArray in viewDidLoad:) to store selected ID's , and in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.
.
//Other codes
.
.
NSLog(#"ID %d", [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue]);
int placeId = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
UIButton* voteButton = (UIButton*)[votePlaceCell viewWithTag:20];
if (!voteButton) {
voteButton = (UIButton*)[votePlaceCell viewWithTag:placeId];
}
voteButton.tag = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
if ([selectedIdArray containsObject:[NSNumber numberWithInt:placeId]) {
voteButton.selected = YES;
} else {
voteButton.selected = NO;
}
return cell;
}
and in
-(IBAction)votePlace:(UIButton *)sender
{
[selectedIdArray addObject:[NSNumber numberWithInt:sender.tag]];
sender.selected = YES;
}
You need to store an array containing information about the background for each cell, and set the background for each cell in cellForRowAtIndexPath.
As you're using selected on the button, create an NSMutableArray with as many entries as the cells, and instead of setting the button itself to selected, change the bool on the selected index of the array, then you can set selected dependent on the value of the desired index of NSMutableArray in cellForRowAtIndexPath.
Related
I've encountered some very strange behaviour with my tableViewCells in a simple list application (iOS).
This is the basic function of my working app :
TableView with 2 sections. First section (e.g. with 2 cells) is always visible. Second section can be shown/hidden with a custom button in the section header. I've created two classes (i.e. FirstSectionItem and SecondSectionItem) both with a boolean property "completed" and some other properties.
After compilations the app runs as expected. Tapping cells results in showing the checkmarks and tapping them again hides the checkmarks (=custom imageView). However after tapping some different cells (random order) or showing/hiding the second section the checkmark (ImageViews) tend to stay checked no matter how much I tap the cells. After a while every cell is checked and can't be unchecked but the boolean values still keep changing.
Here's part of the code:
#property NSMutableArray *sectionTitleArray;
#property NSMutableDictionary *sectionContentDict;
#property NSMutableArray *firstSectionItems;
#property NSMutableArray *secondSectionItems;
ViewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
if (!self.sectionTitleArray) {
self.sectionTitleArray = [NSMutableArray arrayWithObjects:#"section1", #"section2", nil];
}
self.firstSectionItems = [[NSMutableArray alloc] init];
self.secondSectionItems = [[NSMutableArray alloc] init];
[self loadInitialData];
self.sectionContentDict = [[NSMutableDictionary alloc] init];
self.arraySection1 = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.firstSectionItems count]; i++)
{
FirstSectionItem *firstSectionItem = [self.firstSectionItem objectAtIndex:i];
[self.arraySection1 addObject:firstSectionItem.itemName];
}
self.arraySection2 = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.secondSectionItems count]; i++)
{
SecondSectionItem *secondSectionItem = [self.secondSectionItems objectAtIndex:i];
[self.arrayFuture addObject:secondSectionItem.itemName];
}
[self.sectionContentDict setValue:self.arraySection1 forKey:[self.sectionTitleArray objectAtIndex:0]];
[self.sectionContentDict setValue:self.arraySection2 forKey:[self.sectionTitleArray objectAtIndex:1]];
}
CellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListPrototypeCell" forIndexPath:indexPath];
// ... cell content ...
NSArray *content = [self.sectionContentDict valueForKey:[self.sectionTitleArray objectAtIndex:indexPath.section]];
//... constraints ...
UIImage *checkmark = [UIImage imageNamed:#"checkmark.png"];
UIImage *noCheckmark = [UIImage imageNamed:#"transparent.png"];
UIImageView *imageView = [[UIImageView alloc] init];
if (indexPath.section==0){
FirstSectionItem *firstSectionItem = [self.firstSectionItems objectAtIndex:indexPath.row];
imageView.image = firstSectionItem.completed ? checkmark : noCheckmark;
}
if (indexPath.section==1){
if(self.sec2isTapped == YES){
SecondSectionItem *secondSectionItem = [self.secondSectionItems objectAtIndex:indexPath.row];
imageView.image = secondSectionItem.completed ? checkmark : noCheckmark;
}
}
[cell.contentView addSubview:imageView];
// ... more constraints
return cell;
}
didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if (indexPath.section ==0){
FirstSectionItem *tappedItem = [self.firstSectionItems objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
}
if (indexPath.section ==1){
SecondSectionItem *tappedItem = [self.secondSectionItems objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
}
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationMiddle];
[tableView endUpdates];
}
I've tried multiple approaches but none of them seem to work. I can't figure out what the problem is.
(I am new to objective C so some parts might seem a bit devious).
Thanks in advance.
The problem is that you are initializing the UIImageView each time cellForRowAtIndexPath is running. But remember that that cells are reused so what you are doing is reusing a cell that has a checkmark and adding a new clear checkmark on top.
What you need to do is either:
Add the imageView in the storyboard, tag it, and user the tag to find it in the code
Subclass UITableViewCell and assign the correct image in there.
There are MANY articles of how to do both online.
I'm a newbie with iOS programming language. I try to use table with button in each row.
when i click button in the first cell, it work pretty well.
but when i scroll down, the cell that i don't click also appear click.
I want to show the clicked button in only cell(s) that I clicked?
Code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
ClassifyCustomCell * cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if ([[[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_SRNO"] isEqualToString:#"I"]) {
cell.editButton.hidden = YES;
cell.folder_name.text = [[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_NM"];
}else{
cell.editButton.hidden = NO;
cell.folder_name.text = [[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_NM"];
cell.editButton.tag = indexPath.row;
[cell.editButton addTarget:self action:#selector(editButtonAction:) forControlEvents:UIControlEventTouchUpInside];
cell.checkButton.tag = indexPath.row;
[cell.checkButton addTarget:self action:#selector(checkButtonActoin:) forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
-(void)checkButtonActoin:(UIButton *)sender{
if (sender.selected == YES) {
sender.selected = NO;
}else if(sender.selected == NO){
sender.selected = YES;
}else {
sender.selected = NO;
}
}
UITableView reuse the state of cell's subviews for new cells. To prevent reusing just configure your subviews explisitly in tableView:cellForRowAtIndexPath:. In your case you need to set selected property of your button to YES, if it was selected, and to NO, if it was not selected.
Add NSMutableArray property to your view controller:
#property (strong, nonatomic) NSMutableArray *arrayForSelectedIndexPaths;
Change your tap method:
-(void)checkButtonAction:(UIButton *)sender{
UITableViewCell *cell = (UITableViewCell *) sender.superview.superview...; //find appropriate number of superviews to get your cell
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
if (sender.selected) {
sender.selected = NO;
[self.arrayForSelectedIndexPaths removeObject:indexPath];
}else {
sender.selected = YES;
[self.arrayForSelectedIndexPaths addObject:indexPath];
}
}
Then in tableView:cellForRowAtIndexPath: add this line:
cell.checkButton.selected = [self.arrayForSelectedIndexPaths containsObject:indexPath];
The button action is SongsSelectionSongs_Click. When I click this button, the button image changing, the button tap count is getting correct and after selected button images also changing, but when I scroll back and forth in the UITableView the button image seems to be randomly changing.
This is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"SongsTAbleViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SongsTAbleViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
btn_songSelect.tag = indexPath.row;
lbl_songLabel.text = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongTitle"];
lbl_artistLabel.text = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongArtist"];
return cell;
}
-(IBAction)SongsSelectionSongs_Click:(id)sender
{
UIButton *button = sender;
CGPoint correctedPoint = [button convertPoint:button.bounds.origin toView:self.tblv_SongslisttableView];
NSIndexPath *indexPath = [self.tblv_SongslisttableView indexPathForRowAtPoint:correctedPoint];
NSLog(#"Button tapped in row %d",indexPath.row);
SelectedAlbumUrl = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongUrl"];
str_songtitle = [[arr_tablVArray objectAtIndex:indexPath.row] objectForKey:#"SongTitle"];
if ([[button backgroundImageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"add.png"]])
{
btn_songsShareButton.userInteractionEnabled = YES;
[btn_songSelect setBackgroundImage:[UIImage imageNamed:#"remove.png"] forState:UIControlStateNormal];
buttonStatus = buttonStatus +1;
[btn_songsShareButton setImage:[UIImage imageNamed:#"share selected.png"] forState:UIControlStateNormal];
}
else
{
[btn_songSelect setBackgroundImage:[UIImage imageNamed:#"add.png"] forState:UIControlStateNormal];
buttonStatus = 1;
[btn_songsShareButton setImage:[UIImage imageNamed:#"share unselected.png"] forState:UIControlStateNormal];
}
}
You are not doing anything within your cellForRowAtIndexPath to select or deselect image. When you reuse a cell, it doesn't change the state of the cell unless you explicitly tell it to in cellForRow. Therefore, it will either reuse a selected or deselected cell (whatever is the first available reusable cell) and put that on the screen as-is.
To fix this issue, you need logic in your cellForRowAtIndexPath method to either select or deselect the image based on what is appropriate.
In general, if your problem has anything to do with "my cells don't show up right when scrolling" odds are you're not reusing your cells properly.
EDIT: in response to your comment, no, I will not rewrite your code. But I will give you some direction.
I would recommend keeping an additional key/value on your arr_tablVArray that will track whether or not the "share" should be enabled or disabled (I would suggest a bool value). This would make it so that you could check whether or not the "share" is enabled/disabled by checking a bool instead of checking the contents of the button's image in your IBAction method.
This info would now be available in your cellForRowAtIndexPath method as well, and you could check the value for the current record in arr_tablVArray and set your images accordingly just like you set your lbl_songLabel and lbl_artistLabel.
//Try It, it's Working Fine
pragma .h File
NSMutableArray * rowIdArray;
pragma .M File
#synthesize rowIdArray;
- (void)viewDidLoad
{
rowIdArray=[[NSMutableArray alloc]init];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [NamesArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
ViewControllerCell *cell = (ViewControllerCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
NSArray *nib;
nib = [[NSBundle mainBundle] loadNibNamed:#"ViewControllerCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// Configure the cell...
cell.nameslbl.text = [NamesArray objectAtIndex:indexPath.row];
cell.nameBtn.tag=indexPath.row;
[cell.nameBtn addTarget:self action:#selector(NamesClick_Tapped:) forControlEvents:UIControlEventTouchUpInside];
NSString *a=[NSString stringWithFormat:#"%d", indexPath.row];
NSString *b=[[NSString alloc]init];
for (int i=0;i<[rowIdArray count];i++)
{
b=[rowIdArray objectAtIndex:i];
if ([a isEqualToString:b])
{
UIImage *buttonImage = [UIImage imageNamed:#"star_selected.png"];
[cell.nameBtn setBackgroundImage:buttonImage forState:UIControlStateNormal];
}
}
return cell;
}
-(IBAction)NamesClick_Tapped:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.NameTableView];
NSIndexPath *indexPath = [self.NameTableView indexPathForRowAtPoint:buttonPosition];
NSString *rowIdStr = [NSString stringWithFormat:#"%d", indexPath.row];
if(![rowIdArray containsObject:rowIdStr])
{
[rowIdArray addObject:rowIdStr];
}else{
[rowIdArray removeObject: rowIdStr];
}
[self.NameTableView reloadData];
}
when you reuse a cell where the button has been already set, the same button appears with the previously set image. Instead of creating a new button every time you need a cell, you should just be resetting the state of an existing button. This link might help you.
I'm a beginner in iOS and I try to get the value of my uiTextField that I created programmatically.
So my problem is that I create a form in an UITableViewController with a .json file. I have created my form, but I don't know how I can get the different values.
In my cellForRowAtIndexPath I created my different elements (I have textFields, textFields with picker and uiswitch). When the user have finished to fill out the form, he click on a "save" button and it is here that I want to get my values.
If someone can help me and put some code for explain .... :) Thanks.
some of my code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSString *cellValue = [self getItemName:indexPath.section and:indexPath.row];
cell.textLabel.text = cellValue;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *itemType=[self getItemType:indexPath.section and:indexPath.row];
NSLog(#"%#",itemType);
if ([itemType isEqualToString:#"text"]) {
UITextField *Reference = [self createTextField];
[cell.contentView addSubview:Reference];
}else if ([itemType isEqualToString:#"checkbox"]) {
UIView *checkbox = [self createCheckbox:indexPath.section and:indexPath.row];
[cell.contentView addSubview:checkbox];
}else if ([itemType isEqualToString:#"picker"]) {
UITextField *Reference = [self createPicker:indexPath.section and:indexPath.row];
[cell.contentView addSubview:Reference];
}else if ([itemType isEqualToString:#"datePicker"]) {
UITextField *Reference = [self createDatePicker];
[cell.contentView addSubview:Reference];
}
return cell;
}
it is here that i create dynamically the elements. For example an uixtField :
-(UITextField*)createTextField{
UITextField *Reference = [[UITextField alloc] initWithFrame:CGRectMake(200 , 10, 200, 40)];
Reference.layer.borderColor=[[UIColor blackColor]CGColor];
Reference.layer.borderWidth=1.0f;
Reference.textAlignment=NSTextAlignmentCenter;
Reference.tag=_tag;
_tag++;
return Reference;
}
http://hpics.li/04b98ca
here it is an example of that i obtained with my dynamical generation.
Use:
[textField setTag:(integer value)]
when you creating fields in cellForRow... method.
Then use in saveMethod this:
[[tableView cellForIndexPath:indexPath] viewWithTag:(integer value)]
for get concrete field of concrete cell.
if ([itemType isEqualToString:#"text"]) {
UITextField *Reference = [self createTextField];
[Reference setTag:1];
[cell.contentView addSubview:Reference];
}
-(void)saveMethod
{
NSString *string = [[[self.tableView cellForRowAtIndexPath:indexPath] viewwithTag:1] text];
}
You can create elements in the method cellForRowAtIndexPath for your cells if after you want to get info from them, because it will be very difficult to get it.
The best way is creating your custom UITableViewCell with all elements you want and after, in the method didSelectRowAtIndexPath to get the info of your elements.
The way I get an indexPath from a view is by checking the superview until I get the parent cell, then using -indexPathForCell:.
- (UITableViewCell *)cellForView:(UIView *)view
{
while (view != nil && ![view isKindOfClass:[UITableViewCell class]]) {
view = view.superview;
}
return (UITableViewCell *)view;
}
- (NSIndexPath *)indexPathForView:(UIView *)view
{
return [self.tableView indexPathForCell:[self cellForView:view]];
}
Overall, this solution will run into problems. Cells do not persist in a table view. As soon as the cell is off the screen it is recycled by the table view.
This means you should not attempt to store data in a cell. A cell is used to present data and get user input, but never store data. Data is meant to be stored in the table data source.
In addition, it means you need to be careful when adding subviews to a cell. As the cell get recycled, the views you added in it's previous use will still be in the cell. You will need to have a cleanup section to -tableView:cellForRowAtIndexPath: to remove all the views you previously added.
My recommendation is to subclass UITableViewCell. You can either have 4 subclasses, one for each JSON type you have, or have 1 subclass which can be instantiated with in the 4 different ways. In my example, I have 1 subclass that can be instantiated 4 different ways.
Keep the different types of cells differentiated by using different reuse identifiers.
Use target/actions and delegates to get input from the controls on the cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = nil;
NSString *itemType=[self getItemType:indexPath.section and:indexPath.row];
NSLog(#"%#",itemType);
if ([itemType isEqualToString:#"text"]) {
cellIdentifier = #"TextCell";
} else if ([itemType isEqualToString:#"checkbox"]) {
cellIdentifier = #"CheckboxCell";
} else if ([itemType isEqualToString:#"picker"]) {
cellIdentifier = #"PickerCell";
} else if ([itemType isEqualToString:#"datePicker"]) {
cellIdentifier = #"DatePickerCell";
}
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
if ([cellIdentifier isEqualToString:#"TextCell"]) {
cell = [MyTableViewCell textCellWithIdentifier:cellIdentifier];
} else if ([cellIdentifier isEqualToString:#"CheckboxCell"]) {
cell = [MyTableViewCell checkboxCellWithIdentifier:cellIdentifier];
} else if ([cellIdentifier isEqualToString:#"PickerCell"]) {
cell = [MyTableViewCell pickerCellWithIdentifier:cellIdentifier];
} else if ([cellIdentifier isEqualToString:#"DatePickerCell"]) {
cell = [MyTableViewCell datePickerCellWithIdentifier:cellIdentifier];
}
}
NSString *itemName = [self getItemName:indexPath.section and:indexPath.row];
cell.textLabel.text = itemName;
if ([itemType isEqualToString:#"text"]) {
NSString *itemValue = [self getItemValue:indexPath.section and:indexPath.row];
cell.textField.text = itemValue;
} else if ([itemType isEqualToString:#"checkbox"]) {
BOOL itemChecked = [self getItemChecked:indexPath.section and:indexPath.row];
cell.checkbox.selected = itemChecked;
} else if ([itemType isEqualToString:#"picker"]) {
NSString *itemValue = [self getItemValue:indexPath.section and:indexPath.row];
cell.pickerLabel = itemValue;
} else if ([itemType isEqualToString:#"datePicker"]) {
NSDate *itemDate = [self getItemDate:indexPath.section and:indexPath.row];
cell.datePickerLabel = itemDate;
}
return cell;
}
For my problem, I have create a NSMutableDictionaryin which i put my element like that :
key : "name"
value : "UITextField"
Like that i can get the textField everywhere in my class.
in .h file
create the dictionary
in .m
just put the element and when you want to go the text value do :
UITextField* myTextField= [dictionnary objectForKey:key];
I have a question about the event value changed for UISwitch, here is my problem in detail.
in numberOfRowsInSection i have loop that calls the a data base method which return #of rows for each section.
I used an array of arrays(BECAUSE OF I HAVE MANY SECTIONS WITH MANY ROWS) that keeps state of UISwitch then update it whenever value changed called, here is the code of the event:
HOWEVER, after all of these UISwitch still resets whenever I scroll up or down. PLEASE HELP ME AS SOON AS POSSIBLE I will appreciate YOUR HELP SOOOOO MUCH .
Thank you in advance.
I think you make logic error in if (sender.on) in -(void)switchChanged:(UISwitch *)sender method because when sender.on == YES you make OFF:) write
-(void)switchChanged:(UISwitch *)sender
{
UITableViewCell *cell = (UITableViewCell *)[sender superview];
NSIndexPath *x =[mainTableView indexPathForCell:cell];
NSMutableArray *repl = [SwitchArray objectAtIndex:x.section];
[repl replaceObjectAtIndex:x.row withObject:(sender.on ? #"ON", #"OFF")];
}
You can double check the value in the table view willDisplayCell: just to make sure you have it right:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UISwitch* uiSwitch = (UISwitch*) cell.accessoryView;
if (uiSwitch != nil && [uiSwitch isKindOfClass:[UISwitch class]]) {
//just make sure it is valid
NSLog(#"switch value at %d-%d is: %#",indexPath.section, indexPath.row, [SwitchArray[indexPath.section] objectAtIndex:indexPath.row] );
uiSwitch.on = [[SwitchArray[indexPath.section] objectAtIndex:indexPath.row] isEqualToString:#"ON"];
}
}
As an aside, you can you use NSNumbers to make the code more readable:
-(void)switchChanged:(UISwitch *)sender
{
UITableViewCell *cell = (UITableViewCell *)[sender superview];
NSIndexPath *x=[mainTableView indexPathForCell:cell];
NSLog(#"%ld", (long)x.section);
//NSLog(#"index for switch : %d", switchController.tag );
NSMutableArray *repl = repl= [SwitchArray objectAtIndex:x.section];
repl[x.section] = #(sender.on);
}
Then where you set the on value:
uiSwitch.on = [[SwitchArray[indexPath.section] objectAtIndex:indexPath.row] boolValue];
Cells get reused. You are creating a new switch every time a cell is used. You should only create a switch once for each cell. Try the following in your cellForRow... method:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
UISwitch *switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
[switchController setOn:YES animated:NO];
[switchController addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = switchController;
[switchController release];
}
UISwitch *switch = cell.accessoryView;