I trying to display results in a UITableView in my iOS application using a custom UITableViewCell. I am able to view the contents of my Array if I use the cell's textLabel, and detailTextLabel properties, but if I try to link the UITableView with the custom cell class to display the contents of the Array, I only get the default values from Interface Builder displaying in my table.
This is the relevant code that I have:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
TransactionList *tList = [_list objectAtIndex:indexPath.row];
/*
cell.transaction.text = tList.transaction;
cell.type.text = tList.type;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"ddMMYYYY"];
NSString *dateAsString = [formatter stringFromDate:tList.date];
cell.date.text = dateAsString;
*/
//this code below displays the contents just fine, but the block of code above does not.
cell.textLabel.text = tList.transaction;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#, %#", tList.type, tList.status];
return cell;
}
The method below is what I have in my CustomTableCell class:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.contentView.frame = CGRectMake(0, 0, 320, 80);
_transaction = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 80, 40)];
[_transaction setBackgroundColor:[UIColor clearColor]];
[_transaction setFont:[UIFont systemFontOfSize:12]];
[_transaction setNumberOfLines:2];
[_transaction setLineBreakMode:NO];
[self.contentView addSubview:_transaction];
_date = [[UILabel alloc] initWithFrame:CGRectMake(100, 5, 80, 40)];
[_date setBackgroundColor:[UIColor clearColor]];
[_date setFont:[UIFont systemFontOfSize:12]];
[_date setNumberOfLines:2];
[_date setLineBreakMode:NO];
[self.contentView addSubview:_date];
_type = [[UILabel alloc] initWithFrame:CGRectMake(200, 5, 80, 40)];
[_type setBackgroundColor:[UIColor clearColor]];
[_type setFont:[UIFont systemFontOfSize:12]];
[_type setNumberOfLines:2];
[_type setLineBreakMode:NO];
_type.lineBreakMode = NO;
[self.contentView addSubview:_type];
}
return self;
}
Where _transaction, _date, and _type are labels. Here is a screenshot of my Interface Builder inside MainStoryboard:
I have tried changing the style from "Basic", to "Custom", to "Subtitle", but that does not help. It only displays the default values of the table, and those settings change the way they appear, but at no point are the contents of my Array showing up in the table. Can anyone see what it is I am doing wrong? I really think the problem is something simple, but unfortunately I can't put my finger on it.
Thanks in advance to all who reply.
You don't show the 3 objects in the Master View cell. Change the 'Style' from Basic to Custom and drop in your objects.
In the 'Identity Inspector' make sure to rename the Class to 'CustomTableCell'.
Do the views (transaction, date & type) have properties in the CustomTableCell.h and are they connected to the 'CustomTableCell' in IB?
Here's an image to point out the last two:
Related
I have a tableview in which custom cells are created/reused for a lot of rows depending upon type of data encountered(i.e. For Date type , cell's textfield picks up the selected date from datePicker and for enum type , it picks the selected data from dropdown picker). Now there is a button at footer which needs to pick up the data from each cell and process it to display further view controller.
Since data in cells are displayed fine after selection(from datepicker or drop down or keypad) but how can we capture these data in footer button method.
Here is the code :-
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [valueArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(cell == nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSString *values = [valueArray objectAtIndex:indexPath.row];
NSString *titles = [titleArray objectAtIndex:indexPath.row];
if([titles isEqualToString:#“enumType”]){
cell.headerInfo.hidden = true;
cell.valueObtained.hidden=true;
UITextField * scheduelText = [[UITextField alloc]initWithFrame:CGRectMake(20, 30, 130, 30)];
NSMutableArray* enumArray = [[NSMutableArray alloc] init];
[enumArray addObject:#"BUSINESS"];
[enumArray addObject:#"CUSTODIAL"];
[enumArray addObject:#"INDIVIDUAL"];
downPicker = [[DownPicker alloc] initWithTextField:scheduelText enumArray];
scheduelText.text = downPicker.text;
[cell addSubview:scheduelText];
}
else if([titles isEqualToString:#"DateType”]){
cell.headerInfo.hidden = true;
cell.valueObtained.hidden=true;
UITextField *dateText = [[UITextField alloc]initWithFrame:CGRectMake(20, 30, 130, 30)];
dateText.placeholder=#"Date";
dateText.inputView = self.datePicker;
UIToolbar *toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UIBarButtonItem *doItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dateDoneButton)];
[toolBar setItems:#[doItem]];
dateText.inputAccessoryView = toolBar;
[cell addSubview:dateText];
}
else if([titles isEqualToString:#“TextType”]){
cell.headerInfo.hidden = true;
cell.valueObtained.hidden=true;
UITextField * accountText = [[UITextField alloc]initWithFrame:CGRectMake(20, 30, 130, 30)];
accountText.returnKeyType = UIReturnKeyDone;
accountText.delegate = self;
accountText.placeholder=#"Account Name";
[accountText setTextColor:[UIColor blackColor]];
[accountText setBorderStyle:UITextBorderStyleNone];
[cell addSubview:accountText];
}
else{
cell.valueObtained.text = values;
cell.headerInfo.text = titles;
}
return cell;
}
- (void)submitButtonPressed:(id)sender
{
//Need to capture the cell data here ?
}
Please help out in this.
There seems to be a problem with your code:
[cell addSubview:scheduelText];
[cell addSubview:dateText];
[cell addSubview:accountText];
Everytime you dequeue the cell will add a new subview to the cell,but never removed.
In my suggestion,you'd better identifier 4 kind of cells with different identifiers,or removesubviews whenever dequeue the cell.
You can set tag for each of the textfield. and get UITextField from tag.
- (void)submitButtonPressed:(id)sender
{
UITableViewCell *cell =[tableview cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
UITextField *txtField =[cell viewWithTag:TAG];
NSLog(#"%#",txtField.text);
}
Also, Please use custom cells for this.
Since you are using dynamic table view there is only an option. Delegate your controls and store their value on 'endEditing'. You can't use viewTag because view is going to be destroyed if is not visible on screen.
Another option is using static tableview and then you can create #IBOutlets for each control.
As I scroll up and down the table view the data in each cell becomes duplicated and unreadable. Does anyone have any suggestions for the below?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateStyle:NSDateFormatterShortStyle];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectMake(10, 12, 250, 20)];
UILabel *label2 = [[UILabel alloc]initWithFrame:CGRectMake(250, 12, 50, 20)];
label1.tag= 666;
label2.tag= 666;
[cell.contentView addSubview:label1];
[cell.contentView addSubview:label2];
// Configure the cell...
President *p = (President *)[self.importedRows objectAtIndex:indexPath.row];
label1.text = p.no;
label2.text = p.name;
UILabel* cellLabel = (UILabel*)[cell viewWithTag: 666];
cellLabel.text = [NSString stringWithFormat:p.no , p.name];
return cell;
}
dequeueReusableCellWithIdentifier caches the generated cells. So if you request a cell which you already created before this cell will NOT be generated again from scratch (meaning that the labels you added before already exists!).
So when adding the labels tag them with a unique number :
label1.tag= 666;
label2.tag= 667;
And before adding them to the cell remove them as follows :
UIView *labelView = [cell.contentView viewForTag:666];
if (labelView != nil) {
[labelView removeFromSuperView];
}
And do the same with the second label.
because you are adding label1 and label2 again and again to cell.
UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectMake(10, 12, 250, 20)];
UILabel *label2 = [[UILabel alloc]initWithFrame:CGRectMake(250, 12, 50, 20)];
[cell.contentView addSubview:label1];
[cell.contentView addSubview:label2];
As the cell is reused, same cell is used for another row, and it already has label1,2. but you are creating label1,2 again and again and adding them to it.
Give different tags for label1,label2.Check if viewWithTag:666 and 667 is present.If not present add them as subview ,if already present, just get them using viewWithTag and change their text values.
The problem here is with below code:
UILabel* cellLabel = (UILabel*)[cell viewWithTag: 666];
cellLabel.text = [NSString stringWithFormat:p.no , p.name];
I have tried your code, commenting these two lines stop overlapping. You can try to change the frame of this label.
I suggest making your own subclass of UITableViewCell which has two UILabel's on it, then in the method you're using above, create instances of your subclass rather than UITableViewCell if the cell doesn't exist, then populate the labels.
In your custom cell implementation file, you'll have to override the 'prepareForReuse' method, and in it set the text of your labels to nil (#""). This properly uses the 'dequeueWithReuseIdentifier' functionality and only creates the labels when necessary, rather than only showing them when required.
A solution where you can gain performance is the following.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// create and add labels to the contentView
}
// retrieve and update the labels
Obviously you could also create your UITableViewCell subclass.
You could also try this swag (fresh answer, get your fresh answer!):
BOOL doesContain = [cell.subviews containsObject:imageView];
if (!doesContain)
{
[cell.contentView addSubview:imageView];
}
imageView.image = yourImage];
Also for a quick way to subclass all of your stuff, check my answer.
I have a UITextField in a UITableView header. When the user enters anything in the UITextFields, the entry gets added to a NSMutableArray.
I want to create a new UITableCell with the value of the UITextField entry whenever textFieldShouldReturn is called.
I tried using reloadData but that seems to empty my array completely.
Any suggestions? Thanks
- (BOOL)textFieldShouldReturn:(UITextField *)task
{
[task resignFirstResponder];
[self.tasksArray addObject:task.text];
NSLog(#"Test %#", self.tasksArray);
}
My cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
SwipeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[SwipeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
[cell setDelegate:self];
[cell.contentView setBackgroundColor:[UIColor whiteColor]];
// Setting the default inactive state color to the tableView background color
[cell setDefaultColor:self.tableView.backgroundView.backgroundColor];
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
[cell.textLabel setText:self.task.text];
self.view = tableView;
cell.mode = SwipeTableViewCellModeExit;
return cell;
}
My UITableView header :
- (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section{
float width = tableView.bounds.size.width;
int fontSize = 18;
int padding = 1;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0,width, fontSize+11)];
view.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
view.userInteractionEnabled = YES;
view.tag = section;
UITextField *task = [[UITextField alloc] initWithFrame:CGRectMake(padding, 2,
width - padding , fontSize + 11)];
task.text = #"Type here";
task.borderStyle = UITextBorderStyleRoundedRect;
task.textAlignment = NSTextAlignmentCenter;
task.backgroundColor = [UIColor whiteColor];
task.textColor = [UIColor blackColor];
task.delegate = self;
task.font = [UIFont boldSystemFontOfSize:fontSize];
[view addSubview:task];
self.tasksArray = [[NSMutableArray alloc] init];
return view;
}
viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
self.tasksArray = [NSMutableArray arrayWithCapacity:0];
self.title = #"Test";
self.navigationController.navigationBar.tintColor = [UIColor darkGrayColor];
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[backgroundView setBackgroundColor:[UIColor colorWithRed:227.0 / 255.0
green:227.0 / 255.0
blue:227.0 / 255.0
alpha:1.0]];
[self.tableView setBackgroundView:backgroundView];
}
Remove [cell.textLabel setText:self.task.text];
And then,
Insert [self.yourTableOutletName reloadData]; after [self.tasksArray addObject:task.text];
Now your code will reload the tableView after adding a object into self.taskArray.
And then,
To reflect your array in tablView use this line.
Insert [cell.textLabel setText:[self.tasksArray objectAtIndex:indexPath.row]]; after [cell setSelectionStyle:UITableViewCellSelectionStyleGray];
This line pulls the data incorrectly: [cell.textLabel setText:self.task.text];
self.view = tableView;
It should be from your array.
Also you never reload data, that should be the last line in textFieldShouldReturn
I created a uitextview inside a uitableviewcontroller programatically but i am unable to edit the textview. Here's an overview to my table layout:
Row1: UILabel
Row2: Uneditable UITextview
Row3: UILabel
Row4: Editable UITextview
Here's what i am doing:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *label = nil;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(indexPath.row%2==0)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 50)];
[label setBackgroundColor:[self.cellBackgroundColor objectAtIndex:indexPath.row]];
[label setText:[self.celltitle objectAtIndex:indexPath.row]];
label.font=[UIFont fontWithName:[self.cellFontName objectAtIndex:indexPath.row] size:[[self.cellFontSize objectAtIndex:indexPath.row] integerValue]];
label.textAlignment = NSTextAlignmentLeft;
[[cell contentView] addSubview:label];
}
else{
UITextView *messageBox= [[UITextView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 150)];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.userInteractionEnabled=YES;
if(indexPath.row==3)
{
[messageBox setEditable:YES];
[messageBox setUserInteractionEnabled:YES];
messageBox.delegate=self;
messageBox.editable=YES;
}
[cell.contentView addSubview: messageBox];
}
return cell;}
I have also set textviewdelegate in header file and textviewshouldbeginediting method but row4 textview is still not editable... Any help?
In addition to making the messageBox setEditable and setUserInteractionEnabled, you ALSO have to make sure those properties are enabled in your UITableViewController as well since the UITextView is nested within it!
[tableView setUserInteractionEnabled:YES];
[cell setUserInteractionEnabled:YES];
[messageBox setEditable:YES];
[messageBox setUserInteractionEnabled:YES];
(*Note, your tableView and TableViewCell both have the same name from this function so I would put that code elsewhere but I added it above just incase)
Try this.. May be it will help you..Its working for me
if(indexPath.row==3)
{
messageBox.delegate=self;
[messageBox setEditable:YES];
[messageBox setUserInteractionEnabled:YES];
messageBox.editable=YES;
[cell addSubview: messageBox];
}
I tried your code..Its working for me.. see the changes bellow
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *label = nil;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nil == cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if(indexPath.row%2==0)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 50)];
[label setBackgroundColor:[self.cellBackgroundColor objectAtIndex:indexPath.row]];
[label setText:[self.celltitle objectAtIndex:indexPath.row]];
label.font=[UIFont fontWithName:[self.cellFontName objectAtIndex:indexPath.row] size:[[self.cellFontSize objectAtIndex:indexPath.row] integerValue]];
label.textAlignment = NSTextAlignmentLeft;
[[cell contentView] addSubview:label];
}
else{
UITextView *messageBox= [[UITextView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 100)];
cell.userInteractionEnabled=YES;
if(indexPath.row==1)
{
// Uneditable UITextview
messageBox.editable=NO;
}
[cell.contentView addSubview: messageBox];
}
}
return cell;
}
You have to initialize the cell´s content view before using it. Try this:
cell.contentView = [[UIView alloc] initWithFrame:CGRectMake(0,0,cell.frame.size.width, 150)];
I was trying to implement a tableview like this one
please read the comment to see the link <1>
My implementation is:
1. i create my cell from a nib!
please read the comment to see the link <2>
For testing purpose i hardcode the heading part of the cell, and i create the rest in the code like this ...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *myCell = (UITableViewCell*)
[self.tableView dequeueReusableCellWithIdentifier:#"CheckedOutOrderTableCell"];
[[NSBundle mainBundle] loadNibNamed:#"CheckedOutOrderTableCell" owner:self options:NULL];
myCell = nibLoadedTableCell;
UILabel *orderConditionLabel = [[UILabel alloc] initWithFrame:CGRectMake(250, (85+([[bigDictionary objectAtIndex:indexPath.row]count]*35)), 64, 21)];
[orderConditionLabel setText:#"Delivered"];
[orderConditionLabel setFont:[UIFont systemFontOfSize:14]];
orderConditionLabel.textColor = [UIColor darkGrayColor];
orderConditionLabel.backgroundColor = [UIColor clearColor];
for(NSInteger i=0; i<[[bigDictionary objectAtIndex:indexPath.row]count]; i++)
{
UILabel *quantityLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 85+(i*35), 42, 21)];
UILabel *foodLabel = [[UILabel alloc] initWithFrame:CGRectMake(85, 85+(i*35), 175, 21)];
UILabel *priceLabel = [[UILabel alloc] initWithFrame:CGRectMake(220, 85+(i*35), 60, 21)];
[quantityLabel setFont:[UIFont systemFontOfSize:15]];
[foodLabel setFont:[UIFont systemFontOfSize:15]];
[priceLabel setFont:[UIFont systemFontOfSize:15]];
[quantityLabel setText:[NSString stringWithFormat:#"%#",[[[bigDictionary objectAtIndex:indexPath.row]objectAtIndex:i]valueForKey:#"quantity"]]];
[foodLabel setText:[NSString stringWithFormat:#"%#",[[[bigDictionary objectAtIndex:indexPath.row]objectAtIndex:i]valueForKey:#"item_name"]]];
[priceLabel setText:[NSString stringWithFormat:#"$ %#.00", [[[bigDictionary objectAtIndex:indexPath.row]objectAtIndex:i]valueForKey:#"price"]]];
[self.view addSubview:quantityLabel];
[self.view addSubview:foodLabel];
[self.view addSubview:priceLabel];
quantityLabel = nil;
foodLabel = nil;
priceLabel = nil;
}
[self.view addSubview:orderConditionLabel];
orderConditionLabel = nil;
return myCell;
}
and of course i also rewrite heightForRowAtIndexPath: and i finally got this one...
http://i.stack.imgur.com/cF7Y4.png
everything seems going right :D all the label are dynamic created and the position goes perfect... then i tried to save any other record.... and got crashed :'(
http://i.stack.imgur.com/RAXMF.png
I check the data I fed into those cells using NSLOG and below is the structure of my "bigDictionary"
2012-05-17 12:17:50.330 LazBuy[53187:11903] show structure (
(
{
"item_name" = "\U8292\U679c\U9752\U8336";
price = 30;
quantity = 1;
},
{
"item_name" = "\U6587\U5c71\U6e05\U8336";
price = 20;
quantity = 3;
},
{
"item_name" = "\U8292\U679c\U9752\U8336";
price = 30;
quantity = 3;
}
),
(
{
"item_name" = "\U51cd\U9802\U70cf\U9f8d\U8336";
price = 15;
quantity = 3;
}
)
)
The data are fed properly, I do not know what is going wrong!
Why the label didnt update properly, do I need to release them? But I cant release as ARC do not let me do the release line.
You are adding the labels to self.view? Theses should be on the tableviewcell.
[self.view addSubview:quantityLabel];
[self.view addSubview:foodLabel];
[self.view addSubview:priceLabel];
and
[self.view addSubview:orderConditionLabel];
Also your tableviewcell reuse should look more like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TVCell" owner:self options:nil];
cell = tvCell;
self.tvCell = nil;
}
// Set your labels text
return cell;
}