Editing UITableViewCell by tag - ios

I have been trying to find a simple answer to something I think something that shouldn't be that difficult but I just either can't find a decent answer or can't wrap my head around it.
I am trying to change/edit the text label content of one specific tableview cell. So for examples sake I would like a UIButton outside of the UITableView but in the same View Controller to change the text within row 2, while keeping the others the same.
I am aware you use viewWithTag but other than that I cannot figure this out! Please help....
This is my code so far
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
EntryCell *cell = (EntryCell *)[contentTable dequeueReusableCellWithIdentifier:#"Cell"];
cell.mainLabel.tag = indexPath.row;
cell.mainLabel.text = #"hello";
return cell;
}
-(void)buttonPressed:(UIButton *)button {
cell.mainLabel = (UILabel *)[contentTable viewWithTag:2];
cell.mainLabel.text = #"goodbye";
}

don't use viewWithTag, use the below to get a reference to the cell
-(void)buttonPressed:(UIButton *)button
{
EntryCell *cell = (EntryCell *)[tblView cellForRowAtIndexPath: [NSIndexPath indexPathForRow:2 inSection:0]];
if(cell != nil)
{
cell.mainLabel.text = #"goodbye";
}
}
EDIT
As david pointed out this will be overwritten if the cell is not visible as cellForRowAtIndexPath: will be called again when it becomes visible. Overwriting this change with whatever you have specified.
You will need to update your data model after this so the change is permanent

Related

tableview viewWithTag not retrieving UIElements objective-c

I am doing using some code that I have seen work before. Essentially a user answers yes or no on a post with some buttons. Pressing yes or no updates the database, which is working correctly, and it also updates the visible UI, which is not working. This UI updates the buttons so they one is selected, other is highlighted and both are disabled for user interaction. Also it makes changes to two UILabels. The method that these buttons calls needs to update the database and retrieve the buttons from the tableViewCell and update the changes I have the methods working in another ViewController so I can not understand the difference here. Here is my cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *simpleTableIdentifier = [NSString stringWithFormat:#"%ld,%ld",(long)indexPath.section,(long)indexPath.row];
NSLog(#" simple: %#",simpleTableIdentifier);
if (indexPath.row==0) {
ProfileFirstCell *cell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[ProfileFirstCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
cell = [self createProfileCell:cell];
return cell;
}else{
YesNoCell *cell =[self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell==nil) {
cell=[[YesNoCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell = [self createYesNoCell:cell:indexPath];
return cell;
}
}
Essentially what this does is create the users profile in the first cell, and load all the questions that user asks. This is the major difference I see between the old tableView and this tableView. In createYesNoCell I create the UIElements and create tags as follows
cell.yesVoteButton.tag=indexPath.row+ yesVoteButtonTag1;
cell.noVoteButton.tag=indexPath.row+ noVoteButtonTag1;
cell.yesCountLabel.tag=indexPath.row+ yesCountLabelTag1;
cell.noCountLabel.tag=indexPath.row+ noCountLabelTag1;
The buttons have the selector that initiates a number of things. It finds which button was pressed by the following.
NSInteger index;
if(sender.tag>=yesVoteButtonTag1){
NSLog(#"Yes button pressed");
votedYes=true;
index=sender.tag-yesVoteButtonTag1;
}else{
NSLog(#"No button Pressed");
votedYes=false;
index=sender.tag-noVoteButtonTag1;
}
UILabel *yesLabel = (UILabel*) [self.tableView viewWithTag:index+yesCountLabelTag1]; // you get your label reference here
UIButton *yesButton=(UIButton *)[self.tableView viewWithTag:index+1+yesVoteButtonTag1];
NSLog(#"Tag IN METHOD: %ld",index+yesVoteButtonTag1);
UILabel *noLabel = (UILabel*) [self.tableView viewWithTag:index+1+noCountLabelTag1]; // you get your label reference here
UIButton *noButton=(UIButton *)[self.tableView viewWithTag:index+noVoteButtonTag1];
These viewWithTag calls are nil when I look at them. The only difference that I can see from my earlier implementation is that the old one had sections and one row, while this one is all rows and one section. So replacing the indexPath.section with indexPath.row should account for that. Also I checked that the tag made in cellForRowAtIndexPath is the same as the row recovered in the yes/no vote method, because it is displaced by one because of the profile cell being created at indexPath.row==0. I tried passing the cell to the yes/no vote method and tried to recover the buttons and labels with contentView as some suggestions made on similar posts. However this didn't seem to solve my problem. Really would appreciate some insight on this.
have you call the '[tableView reload]' method to update the UITableView, it may helps.
Firstly, the table reuse identifier should be used for types of cells, not one for each cell. You have two types, so you should use two fixed reuse identifiers.
ProfileFirstCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"ProfileCell"];
if (cell == nil) {
cell = [[ProfileFirstCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"ProfileCell"];
}
and
YesNoCell *cell =[self.tableView dequeueReusableCellWithIdentifier:#"YesNoCell"];
if (cell==nil) {
cell=[[YesNoCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"YesNoCell"];
}
Secondly, rather than trying to get a reference to a cell after creating the table, which isn't working for you, you should initialize the cells completely when they are created. (TableView won't create cells unless they're visible, so you shouldn't rely on their existing at all.)
createProfileCell should really be called initializeProfileCell, because you're not creating the cell in it - you already did that in the line above, or recovered an old one.
Then your call to initializeProfileCell can take a flag specifying whether it is a Yes or No cell and set its properties accordingly.
cell = [self initializeProfileCell:cell isYes:(indexPath.section==0)];
Similarly with createYesNoCell --> initializeYesNoCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"YOURCELL_IDENTIFIER";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *title = (UILabel*) [cell viewWithTag:5];
UILabel *vensu =(UILabel*) [cell viewWithTag:7];
vensu.text = #"YOUR TEXT";
title.text = #"YOUR TEXT";
return cell;
}

How to add UISWitch to few rows in UITable in iOS?

I have a UITableView which contains so many rows.In my screen there can be UISwitch added for few rows in UITableView.Please tell me how can i do this?
Should i create a custom cell with a UISwitch & show or hide the UISwitch.
Should i add the UISwitch directly from the code in cellForRowAtIndexPath:.
Any suggestions please?
EDIT:
I have tried this code but this does not work.
SettingsCell *cell;
static NSString *CellIdentifier = #"SettingCell";
if (cell == nil)
{
cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
[cell setSelectionStyle:UITableViewCellSelectionStyleDefault];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
}
if(indexPath.row==2 || indexPath.row==3)
{
cell.switch_value.hidden=false;
}
else
{
cell.switch_value.hidden=true;
}
cell.label_text.text = [VALUES objectAtIndex:indexPath.row];
return cell;
If you are creating a new cell then you should use that cell for only required rows. For rest of the rows you should not take pain of hiding the switch.
If you create UISwitch directly from the code in CellForRowAtIndexPath, then you should take care while re-using the cell. If you use different identifier for both cell types, the show/hide problem will get resolved.
Both solutions work here : you can add an UISwitch in a UITableViewCell in cellForRowAtIndexPath: : be just careful to check that no previously created UISwitch exists before creating a new one.
The second solution consists in using a custom UITableViewCell subclass.
I prefer this solution because you don't have to cast your subviews or use viewWithTag: method, or even to check if your custom subview was already created.
You should create some simples subclasses, such as PickerCell, SwitchCell, TextFieldcell : thus you will have your own set of custom UITableViewCell subclasses ready to be used within all your projects.
Assuming you have registered your reuse identifier, try this :=
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SettingCellIdentifier = #"SettingCell";
static NSString *StandardCellIdentifier = #"StandardCell";
if (indexPath.row == 2 || indexPath.row == 3) {
SettingsCell *cell = (SettingsCell *)[tableView dequeueReusableCellWithIdentifier:SettingCellIdentifier forIndexPath:indexPath];
[cell setSelectionStyle:UITableViewCellSelectionStyleDefault];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
cell.label_text.text = [VALUES objectAtIndex:indexPath.row];
// Do whatever you want with the switch here
return cell;
}
else
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:StandardCellIdentifier forIndexPath:indexPath];
// instantiate a regular UITableViewCell
cell.label_text.text = [VALUES objectAtIndex:indexPath.row];
return cell;
}
}

Get UItextFields text from custom UITableView

I have a custom UITableViewCell with a UITextField (which is linked to the custom cells class). I am trying to access the textField from my VC class.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if ([indexpath row] == 2) {
menuCell.nameTextField.delegate = self;
}
return cell;
}
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
}
How do I get the textFields text from textFieldDidEndEditing?
Depending on where you want to access this text depends on how difficult it is.
Want to access the text in cellForRowAtIndex - (very easy)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if ([indexpath row] == 2) {
menuCell.nameTextField.delegate = self;
}
NSString * text = menuCell.nameTextField.text;
return cell;
If you want to access the text anywhere in the VC and the menuCell is unique (there is only one of them) - (medium difficult)
In your header file add the custom cell as a class
#class menuCell;
This means you can set it a variable in the interface
menuCell * _menuCell;
Next in cellForRowAtIndex you want to allocate this custom cell
- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == bCustomCellSection) {
if (!_menuCell) {
_menuCell = [tableView_ dequeueReusableCellWithIdentifier:bProfileNameCell];
_menuCell.nameTextField.delegate = self;
}
_menuCell.nameTextField.placeholder = #"Name";
_menuCell.selectionStyle = UITableViewCellSelectionStyleNone;
return _menuCell;
}
...
}
This means that we now have access to the menu cell from anywhere in the VC and can get the text by calling
_menuCell.nameTextField.text
Multiple custom cells with multiple textfields - (tough)
I have never done this but would probably do it one of two ways
a) Create an array and as we are creating the custom cells add a pointer to the textFields to the array each time. We can then access the textField we want from that array
For this method I would add the custom cells to a mutable array defined in the interface
NSMutableArray * cellsArray;
remember to initialise it in viewDidLoad
cellsArray = [NSMutableArray new];
Then in cellForRowAtIndex i would add the cell each time
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
[cellsArray addObject: menuCell];
This obviously depends on how many sections we have. If we have more than one section it gets more complicated again:
Then we would need to add an array for each section to an overall array. This is quite complicated and could have a whole question on its own, there is a good link of how to do this here:
Once you have an array of cells (or an array of arrays of cells) you can call the cell you want based on the indexPath and get the textField
b) Call a pointer to the specific cell we want
menuCell * menuCell = [self tableView:table cellForRowAtIndexPath:indexPath];
and then get the textField from this cell as we did previously.
Remember you can calculate your own indexPath if you want to create one outside of cellForRow:
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
This method is pretty good if you want to access a specific cell but a bit cumbersome if you want to access it a lot and keep having to call this code all over your VC
Hope this helps
If you are asking how to get the text from the delegate method textFieldDidEndEditing, then you simply do this:
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
NSString *textFieldText = textfield.text;
}
However, if you have multiple textFields and you want to know what textfield is calling the delegate, you could tag your textField:
[myTextField setTag:indexPath.row]
and then put a if statement in the delegate textFieldDidEndEditing like this:
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
if(textfield.tag == index0) do something..
else if(textfield.tag == index1) do something..
}

Questions with Prototype Cell and UITableView

I have two kind of cell, one a standard title-subtitle cell, and another custom cell with two UITextField. And they have different identifier, VIEW and EDIT.
In my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I need to create two kind of cell. At any time, I have only one cell in edit, so I create a NSUInteger to keep track of which cell is being edited.
My code looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell;
if ( rowInEdit == indexPath.row )
{
cell = [tableView dequeueReusableCellWithIdentifier:#"EDIT"];
if ( !cell )
{
cell = [[UITableViewCell alloc]init];
}
RLSite* site = [[RLSettings settings]siteAtIndex:indexPath.row];
[[cell textLabel]setText:site.name];
[[cell detailTextLabel]setText:site.url];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:#"VIEW"];
if ( !cell )
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"VIEW"];
}
RLSite* site = [[RLSettings settings]siteAtIndex:indexPath.row];
[[cell textLabel]setText:site.name];
[[cell detailTextLabel]setText:site.url];
}
return cell;
}
Notice that my first part is definitely flawed. I don't know how to create a cell with prototype, and how to assign reuseIdentifier to it. Furthermore, I don't know how to access those UITextField in that cell once it's created.
Can anyone help me?
e. how to create a cell with prototype you can follow these tutorials as I also learned it from one of these tutorials
Tutorials
First one Which I referred.
Second one
And to excess the added text views you need to assign them tag values (obviously distinct).
Then use the below code to excess them in side your tableView:cellForRowAtIndexPath: method.
UITextField *txtField = (UITextField *)[cell viewWithTag:8];
Here replace the 8 with your tag value :)

Cannot access the Custom UILabel in a Custom UITableViewCell

this is Nsr (just a beginner in xcoding), using xcode 4.3.3,
I've made a Custom UITableview with Custom UITableviewcell through storyboarding,
I have a UIBUtton and a UILabel in my custom cell.
i'v remove the cell selection (also cleared the background) so that only the buttons can be accessable which works as a backgound for the custom UILabel.
Now there are bunch of buttons since of using data array, and when i click any button, it segues to the other view (detail view), all i wanted is to set the custom Label (set over the detail view) from the previous selected button with "Label"...
means new Label = previous page's clicked Label from the custom tableview..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
Custom *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Custom alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.myLabel.text = [myArray objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.myTable reloadData];
}
I hope you get my problem, very sorry for my poor english..
Please help me, im in a real mess, coz this problem already took my 3 days :(
Thanx in advance, Cheers.
function return Custom cell but in header you write UItableviewCell change this to Custom

Resources