I have TableCellViewController for managing cells in my UITableView. Each cell has a label na UISwitch (dictTypeSwitch). A want to assign method to switch events so I can save the state of button.
So far I've done this:
assign setState function to object:
[cell.dictTypeSwitch addTarget:self action:#selector(setState:) forControlEvents:UIControlEventTouchUpInside];
function for handling event:
- (void)setState:(id)sender {
BOOL state = [sender isOn];
NSString *rez = state == YES ? #"YES" : #"NO";
NSLog(rez);
}
From sender I get UISwitch object from which I can get state.
So far everything is ok.
But if I want to save the state of UISwitch, I have to get rowIndex for this cell.
How can I achieve this?
The cells are made inside function cellForRowAtIndexPath. Se the code bellow:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"DictionariesTableCellViewController";
DictionariesTableCellViewController *cell = (DictionariesTableCellViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"DictionariesTableCellViewController" owner:nil options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (DictionariesTableCellViewController *) currentObject;
break;
}
}
}
// Configure the cell...
cell.dictTypeLabel.text = [NSString stringWithFormat:#"row - %i",indexPath.row];
[cell.dictTypeSwitch addTarget:self action:#selector(setState:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
Thanks
You can use the UISwitch's .tag property to store an arbitrary integer. This can be set to the row index.
If it is possible to find the UITableViewCell from UISwitch's parent, you could get the index path with
NSIndexPath* indexPath = [theTableView indexPathForCell:theCell];
Related
Here tableview after scrolling 2 3 times full up and down add images to all cells. Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:#"HomeCell"];
if (cell == nil) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"HomeCell"] ;
}
VenueDC *venueObj = [subSubCategoriesArray objectAtIndex:indexPath.row];
cell.lblName.text = venueObj.name;
if ([venueObj.imagesArray count] > 0) {
[cell.ivVenue setImage:venueObj.ivVenue];
[cell.ivVenue setHidden:NO];
cell.lblName.frame = CGRectMake(80, cell.lblName.frame.origin.y, 200, cell.lblName.frame.size.height);
}
venueObj = nil;
return cell;
}
Any idea what's happening here?
Image is only in one object, on first load it shows one cell with image, but after scrolling it starts showing images on other cell too.
Solved it like this, first i set the lblName frame to its original position, so it reset its position everytime the cell is used
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:#"HomeCell"];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HomeCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (HomeCell *) currentObject;
break;
}
}
}
VenueDC *venueObj = nil;
venueObj = [subSubCategoriesArray objectAtIndex:indexPath.row];
cell.lblName.text = venueObj.name;
[cell.ivVenue setHidden:YES];
cell.lblName.frame = CGRectMake(20 , 19, 250, 20);
if (venueObj.ivVenue) {
[cell.ivVenue setImage:venueObj.ivVenue];
[cell.ivVenue setHidden:NO];
cell.lblName.frame = CGRectMake(80, cell.lblName.frame.origin.y, 200, cell.lblName.frame.size.height);
}
return cell;
}
UITableViewCells get reused, which is what the dequeueReusableCellWithIdentifier: method does. To save memory the UITableView only instantiates as many cells as it is possible to see at any given point, and then just keeps on reusing them. Because of this you should always clean up your cells before reuse, that is reset all its content to nil.
If you are using a custom table view like in your case HomeCell then override -(void)prepareForReuse and set up the image to nil there.
It is happening because your cell is reuse so write this code:
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HomeCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (HomeCell *) currentObject;
break;
}
}
}
You Need to add only one line in cellForRowAtIndexPath
NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
And change
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:#"HomeCell"];
if (cell == nil) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"HomeCell"] ;
}
VenueDC *venueObj = [subSubCategoriesArray objectAtIndex:indexPath.row];
cell.lblName.text = venueObj.name;
[cell.ivVenue setImage:nil];
if ([venueObj.imagesArray count] > 0) {
[cell.ivVenue setImage:venueObj.ivVenue];
[cell.ivVenue setHidden:NO];
cell.lblName.frame = CGRectMake(80, cell.lblName.frame.origin.y, 200, cell.lblName.frame.size.height);
}
venueObj = nil;
return cell;
}
You need an else statement:
else {
venueObj = nil;
}
I have a TableView and I am Using Custom TableCell.In TableCell I have a button. Now in TableView I have created a Bool Value to check whether the Check button is Selected or not.
The problem is When I scroll the Table the cell get reused so the button gets Automatically deselected.
if (checkButton.selected==NO) {
NSLog(#"ooo");
checkButton.selected=YES;
checkSelected=YES;
}
else {
NSLog(#"Okkkkk");
checkButton.selected=NO;
checkSelected=NO;
}
I have an idea to Subclass UIButton with a custom Property of BOOl.But I dont know to workout. Can anyone help me out?
You can keep a track of button selected using the array. Just set value 1 at particular index when button is selected. And set it to 0 when it's deselected.
And then while creating the cell you can check in as follows:
if ([[arr_Check objectAtIndex:indexPath.row] isEqualToString:#"0"])
checkButton.selected=NO;
else
checkButton.selected=YES;
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%i%i",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
else
{
NSArray *cellSubs = cell.contentView.subviews;
for (int i = 0 ; i < [cellSubs count] ; i++)
{
[[cellSubs objectAtIndex:i] removeFromSuperview];
}
}
UICheckBox *checkBox = [[UICheckBox alloc] initWithFrame:CGRectMake(0, 0, 44.0, 44.0)];
checkBox.tag = indexPath.row;
checkBox.titleLabel.tag = indexPath.section;
[checkBox addTarget:self action:#selector(checkBoxPressed:) forControlEvents:UIControlEventTouchUpInside];
for (NSIndexPath *temp in selectedObjects) {
if ([temp isEqual: indexPath]) {
checkBox.selected = TRUE;
}
}
[cell.contentView addSubview:checkBox];
return cell;
}
-(void)checkBoxPressed:(UICheckBox*)sender
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:sender.titleLabel.tag];
if (sender.selected)
[selectedObjects removeObject:indexPath];
else
[selectedObjects addObject:indexPath];
sender.selected = !sender.selected;
NSLog(#"\n\n%#",selectedObjects);
}
Here selectedObjects is a global NSArray and UICheckBox is a subClass of UIButton
#interface CustomButton : UIButton
#property(nonatomic) BOOL isSelected;
// DO NOT FORGET TO SYNTHESIZE MY isSelected
#end
since you are using a custom cell. you can just make a property CustomButton in your custom cell.
#interface YourCustomCell : UITableViewCell
#property(nonatomic, strong) CustomButton *button;
#end
in your cellForRowAtIndexPath method
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
YourCustomCell *cell = (YourCustomCell*)[tableView dequeueReusableCellWithIdentifier:cellType];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellType owner:nil options:nil];
cell = (YourCustomCell*)[nib objectAtIndex:0];
}
//you can add a target to your button here
cell.button addTarget:self action:#selector(changeButtonState:).....
if(cell.button.isSelected == YES)
NSLog(#"selected");
else
NSLog(#"not selected");
-(void)changeButtonState:(CustomButton*)button
{
if(button.isSelected) button.isSelected = NO;
else button.isSelected = YES;
[yourTableView reloadData];
}
I subclassed UITableViewCell and added a button to it. How do I response to the event when the button is touched? I also need to know which index path was the button pressed on.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomTableCell";
CustomTableCell *cell = (CustomTableCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomTableCell"
owner:nil options:nil];
for (id currentObjects in topLevelObjects){
if ([currentObjects isKindOfClass:[StatusTableCell class]]){
cell = (StatusTableCell *) currentObjects;
break;
}
}
}
cell.customButton.tag = indexPath.row;
return cell;
}
If you have added the UIButton by code in your UITableViewCell Subclass you can use the following code to add an action for it.
//In UITableViewCell subclass
[customButton addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchDown];
And then you have already written the code for accessing the row number by setting,
cell.customButton.tag = indexPath.row;
You can get the tag value in the aMethod and access the indexPath.row value like below,
//In UITableViewCell subclass
-(IBAction)aMethod:(UIButton*)button
{
NSLog(#"indexPath.row value : %d", button.tag);
}
You can assign the IBAction in the CustomTableCell Nib and in the function do something like this:
- (IBAction) btnDoSomethingPressed:(id)sender {
NSIndexPath *indexPath = [yourTableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
//Use indexPath (or indexPath.row) like you would in a UITableViewDelegate method
}
This assumes that yourTableView is an instance variable assigned to your table.
I have a UITableView with about 20 cells, in each cell there are three UITextFields. I did NOT subclass UITableViewCell, but when setting up each cell I set the textfields tag value to a constant plus the row number. So for each row the tag of the textfield is incremented by one.
When I run the app and enter a value in for example row one, it may reappear on row 12. The behavior is not the same each time i run the app.
I should add that I have an array storing the contents entered in each textfield. When a textfield is edited, I save the new value to the array and when the cell is again requested by the tableview i set the textfields value to that stored in the array.
Does this have something to do with reusing UITableViewCells?
When reusing a cell, can textfields in different rows get the same tag numbers? Say for example that the first cell (textfield tag=1001) is reused on row 12, then we have two textfields with the same tag number. If I then enter a value on row 1 and later load row 12, the value from cell one will be loaded from the array and put in row 12 also.
If this is happening, how do I fix it?
Each cell does not have a reference to the textfield, so I don't think I can edit a textfield's tag value by just having access to the cell which it is in.
EDIT:
Here is the code for UITableView:cellForRowAtIndexPath:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//Modify cell, adding textfield with row-unique index value
cell = [self modifyCellForHoleInfo:cell atIndexPath:indexPath];
}
cell.accessoryType = UITableViewCellAccessoryNone;
// Load value for textfield stored in dataArray
((UITextField *)[cell viewWithTag:1000+indexPath.row]).text = [dataArray objectAtIndex:indexPath.row];
Thanks!
The issue is that when the cell is reused (i.e. dequeueReusableCellWithIdentifier returns non-nil), the cell is returned with the existing UITextView. To maintain the uniqueness of the tags, it'll be better to remove any previous UITextField:
- (void)removeExistingTextSubviews:(UITableViewCell *)cell
{
NSMutableArray *toRemove = [NSMutableArray array];
// I don't know if you have non-TextField subviews
for (id view in [cell subviews]) {
if ([view isKindOfClass:[UITextField class]] && view.tag >= 1000) {
[toRemove insert:view];
}
}
for (id view in toRemove) {
[toRemove removeFromSuperView];
}
}
...
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
} else {
[self removeExistingTextSubviews:cell];
}
//Modify cell, adding textfield with row-unique index value
cell = [self modifyCellForHoleInfo:cell atIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
// Load value for textfield stored in dataArray
((UITextField *)[cell viewWithTag:1000+indexPath.row]).text = [dataArray objectAtIndex:indexPath.row];
Please note that I haven't compiled the code, but it should serve as a starting point.
Just get the textfield text into Dictionary setObject by label text and again check by label Text assign the text to corresponding Textfield.. here is my code...
//In Interface
NSMutableDictionary *amounts;
amounts =[[NSMutableDictionary alloc]init];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MoneyEntryIdentifier";
static NSString *CellNib = #"MoneyEntry";
MoneyEntryTableViewCell *cell = (MoneyEntryTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (MoneyEntryTableViewCell *)[nib objectAtIndex:0];
}
UILabel *lblname = (UILabel *) [cell lblMemName];
lblname.tag =100;
UITextField *txtfield = (UITextField *)[cell textAmount];
txtfield.tag =indexPath.row;
[txtfield addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
lblname.text = tabledata[indexPath.row];
txtfield.placeholder = [NSString stringWithFormat:#"%ld",(long)indexPath.row];
if ([amounts valueForKey:lblname.text] != nil) {
txtfield.text = [amounts valueForKey:lblname.text];
} else {
txtfield.text = #"";
}
cell.selectionStyle =UITableViewCellSelectionStyleNone;
return cell;
}
-(void)textFieldDidChange:(UITextField *)txtField
{
UILabel *label = (UILabel *)[txtField.superview viewWithTag:100];
NSString *labelString = label.text;
NSString *textFieldString = txtField.text;
[amounts setObject:textFieldString forKey:labelString];
}
Change the nib to your tableview cell...
I've a table view. In each cell (row), i want to show two buttons. initially both are red in color. when one button is clicked, it turns green and other will be in red.
I created a view which has two buttons. I am using IB to create the view.
i'm using following code to show the my table view to show the custom view:
- (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] autorelease];
}
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:#"CellView"
owner:self options:nil];
CellView *myView;
for (id object in bundle) {
if ([object isKindOfClass:[CellView class]])
myView = (CellView *)object;
}
NSString* str = [testArray objectAtIndex:indexPath.row];
NSArray* arr = [str componentsSeparatedByString:#" "];
myView.left.titleLabel.text = [arr objectAtIndex:0];
myView.right.titleLabel.text = [arr objectAtIndex:1];
[cell.contentView addSubview:myView];
return cell;
}
Above code works fine but when the button is clicked, its showing the button with text that I created in IB. I am not understanding why is it happening?
Can some one guide me how to show a button in cell and handle its action?
I think you have to specify the titleLabel for different states of button. Then this code will work fine.