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 :)
Related
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;
}
I've been doing a lot of research, but cannot find an answer or a guide to help.
I would like to have more than one custom cell in a Table View. For example, the first cell may display an image, while the 2nd cell displays some information, and then the third displaying something else (All cells different sizes). I've tried a lot of code but can't get it right, I've also been watching tutorials but am still unable to do this. Would it be easier to do this in a blank UIView with no cells?
Thanks, help and advice is greatly appreciated.
Let's say you have one table view with one section. Here's how I usually do this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
id cell = nil;
switch (indexPath.row) {
case 0:
cell = [self dequeCellIdentifier:#"FirstTypeOfCell"];
break;
case 1:
cell = [self dequeCellIdentifier:#"SecondTypeOfCell"];
break;
case 2:
cell = [self dequeCellIdentifier:#"ThirdTypeOfCell"];
break;
default:
cell = [self dequeCellIdentifier:#"JustThrowThisInThere"];
break;
}
return cell;
}
To dequeue the cell, make sure you specify its identifier in XIB interface and add this method to dequeue:
- (id)dequeCellIdentifier:(NSString *)cellIdentifier {
id cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil][0];
}
return cell;
}
To get different heights for cells, use the - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case 0:
return 40.0;
case 1:
return 100.0;
default:
return 50.0;
}
}
Create a custom class for each cell that inherits from UITableViewCell. Make sure to also crete a XIB when you create the class. This give you the flexibility to design your cell in the interface builder.
Check out this answer: How do you load custom UITableViewCells from Xib files?
PS. Don't forget to change the height of the cells in
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
You can use prototype cells in storyboard. basically what you do is create one prototype cell for each type and create a UITableViewCell subclass for each of them. also give each a unique ID. all these steps are explained in detail here (follow upto Modifying the CarTableViewCell Class section).
Now is the tricky part. The above tutorial only explains how to create one custom cell. if you want multiple types of custom cells, create all those cells with unique reuse identifier and subclasses. now i'm not sure if this is the right approach but here's what I usually do :
in CellForRowAtIndexPath:
if([cellType isEqualToString:#"DefaultCell"])
{
MyTableDefaultCell *cell = [self.tableViewOutlet dequeueReusableCellWithIdentifier:#"DefaultCell" forIndexPath:indexPath];
if(cell == nil)
{
cell = [[MyTableDefaultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"DefaultCell"];
}
//Do your thing here.
return cell;
}
else if([cellType isEqualToString:#"SegmentedControlCell"])
{
MyTableSegmentControlCell *cell = [self.tableViewOutlet dequeueReusableCellWithIdentifier:#"SegmentedControlCell" forIndexPath:indexPath];
if(cell == nil)
{
cell = [[MyTableSegmentControlCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SegmentedControlCell"];
}
// Setup cell here.
return cell;
}
and dont forget to return the appropriate heights for each cell in heightForRowAtIndexPath:. cheers.
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
So I'm trying to make two tableviews in one view and I'm having some trouble.
I've read some other response on how to do it but they don't exactly help me.
In my .h file I made two outlets for two views calling them myFirstViewText and mySecondViewTex
So in my m files for - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
I want to be able to print out seperate values in each different controller and I'm not too sure since you only return 1 cell?
So far i've Done this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Rx";
static NSString *CellIdentifier2 = #"allergies";
UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:CellIdentifier];
UITableViewCell *cell2 = [tableView dequeueReusableHeaderFooterViewWithIdentifier:CellIdentifier2];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (!cell2) {
cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
}
if (tableView == self.myFirstTextView ) {
cell.textLabel.text = #"HI JAZZY";//[RxDict objectAtIndex:indexPath.row];
}
if (tableView == self.mySecondTextView) {
cell.textLabel.text = #"BYE JAZZY";//[RxDict objectAtIndex:indexPath.row];
}
tableView = self.mySecondTextView;
cell2.textLabel.text = #"I love Jazzy :D";
return cell2;
This prints "I love Jazzy" in my first TableView and nothing gets printed in the second one. Why does this happen and how can I fix it?
Thanks :D
This method gets called by all tableViews that have an instance of your class set as their dataSource.
This means you need to check which tableView was asking for cell number so-and-so.
So, your method should basically look like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == rxTableView) {
//prepare and return the appropriate cell for *this* tableView
}
else if (tableView == allergiesTableView) {
//prepare and return the appropriate cell for *this* tableView
}
return nil; //because you don't expect any other tableView to call this method
}
My suggestion would be to set a tag on both of your table views and then in your tableview dataSource methods check for which the tag the table view your are in. So for instance some where in your code you can do:
myFirstTableView.tag = 1;
mySecondTableView.tag = 2;
later when your are in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.tag == 1)
cell.textLabel.text = #"HI JAZZY";//[RxDict objectAtIndex:indexPath.row];
if (tableView.tag == 2)
cell.textLabel.text = #"BYE JAZZY";
}
Also if you have 2 tableviews with different sizes you can achieve this like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag == 1)
return 1;
else if (tableView.tag == 2)
return 2;
}
One approach I don't see implemented too often is actually to use a NSObject subclass to act as the delegate and datasource for each table, not the view controller. It removes the need for the "if (tableView == someTable) ..." code, and might make both your view controller and UITableView code maintainable and readable.
You'd create an NSObject subclass for each table. These subclasses would contain the desired implementation of your UITableView datasource and delegate methods. You'd then instantiate one of each in your view controller and hook each up to its appropriate table.
Problem 1:
tableView = self.mySecondTextView;
cell2.textLabel.text = #"I love Jazzy :D";
return cell2;
What you are doing here is always returning cell2, setting its text "I love jazzy :D" so it will always fill the first table view because you would not have set the tableView=mySecondTextView before entering into the method. The delegate is always targeting firstTableView.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Problem 2:
if (tableView == self.myFirstTextView ) {
cell.textLabel.text = #"HI JAZZY";
//[RxDict objectAtIndex:indexPath.row];
//for printing in first table view return cell here like
return cell;
}
if (tableView == self.mySecondTextView) {
cell.textLabel.text = #"BYE JAZZY";
//[RxDict objectAtIndex:indexPath.row];
//for printing in second tableview return cell two here
return cell2;
}
Make sure the table you want to target is set before entering into this function. You can set it in numberofsection method, the view didload method or somewhere else from where you want to show or target table view (like clicking on some button). But you can't set it here.
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