I am trying to pass the text lable that is in the uitableviewcell I have created but I am not sure of the parameters that are needed in order to do this.
I have an NSObject with a method that has an NSString object as a parameter, this is where I would like to pass the information from my uitableviewcell label too...
I have #imported the .h file and set up the object inside the views tableViews:didSelectRowAtIndexPath method but I am just not sure how to pass it the text from the lable, this is what I have tried but I have a compatibility warning..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//initalize object to hold search parameters
VehicleSearchObject *vehicleSearchObject = [[VehicleSearchObject alloc] init];
[self.navigationController popViewControllerAnimated:YES]; //pops current view from the navigatoin stack
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//--- this if block allows only one cell selection at a time and is passing the text in the cells label back to the object
if (oldCheckedData == nil) { // No selection made yet
oldCheckedData = indexPath;
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[vehicleSearchObject GetManufacturers:[[cell textLabel] objectAtIndex:[indexPath row]] // This is where I try to pass the text back but not sure how to do it..
}
else {
UITableViewCell *formerSelectedcell = [tableView cellForRowAtIndexPath:oldCheckedData]; // finding the already selected cell
[formerSelectedcell setAccessoryType:UITableViewCellAccessoryNone];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark]; // 'select' the new cell
oldCheckedData=indexPath;
}
}
You have to do this.
[vehicleSearchObject GetManufacturers:cell.textLabel.text];
You can reference the cell label text by simply doing:
cell.textLabel.text
i.e.
[vehicleSearchObject GetManufacturers:cell.textLabel.text];
[[cell textLabel] setText:[vehicleSearchObject GetManufacturers:[[cell textLabel] text]];
Related
just created an UITableView,
trying to display some custom data from an array, but what ever I do, i get no text displayed.
NSLog tell me the right text and right amout but no text in table cell.
here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"test";
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
Things to check:
Is cellForRowAtIndexPath getting called? Put a breakpoint in
Make an array in ViewDidLoad (property, alloc'd) and addObjects #"One", #"Two", #"Three", nil and then cell.textLabel.text = [theArray objectAtIndex:indexPath.row];
IfcellForRow is being called, this will show in the cells.
What doesConfigureCell do? Include the code please.
Also check your tableView delegate methods are being called (NumberofRowsInSection etc)
Always set cell properties (text, images, accessory views, etc) in the
tableView:willDisplayCell:forRowAtIndexPath
delegate method.
UITableView sometimes send a prepareForReuse to the cell after it is returned from
tableView:cellForRowAtIndexPath
which causes the cell to reset it's labels and images.
In this screen shot you can see that I have added UITableView in UIViewController then customized the UITableViewCell by adding some labels in it. But the issue is when I run the application. All of the cells are empty. There are no labels at all.
I am not getting what can be the issue. I have searched the web and read tutorials but couldn't resolve it.
I resolved this issue by myself, just after little effort.
Actually when you create a custom cell you have to do these things:
Setup the labels, images etc on storyboard cell.
Create a custom cell class (inheriting from UITableViewCell)(CustomCell.h & .m), CustomCell.h having all of the properties as iboutlet for labels, images etc. and synthesize them all in implementation.
After creating this custom class go back to storyboard, select the custom cell, change its class to the CustomCell and give it some identifier like "MyCustomCell", then right click on the custom cell and connect the IBOutlets with labels etc.
Now import CustomCell class in the class where you are implementing the UITableView and use the properties you defined in CustomCell class.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyCustomCell";
CustomCell*cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the provided setImageWithURL: method to load the web image
// Ensure you use a placeholder image otherwise cells will be initialized with no image
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://example.com/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder"]];
cell.myCustomLabel.text = #"My Text";
return cell;
}
I did this all and my issue was resolved and please don't forget to connect the delegates & datasource and table.
Hope this will help others.
It is little bit late but you can solve your problem by setting the background color of your view as Clear Color from your storyboard.
in the tableview's delegate method , cellforrowatindexpath has a uitableviewcell inside it , there should be an identifier in the initialization of this cell. possibly it is "cell" or "cellIdentifier" .
you just need to select your cell from storyboard and enter this identifier string to the storyboard , where uitableviewcell's attribute inspector stays.
hope this helps.. :)
First Set cell identifier in storyboard #"Cell"
then set tag of label
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}
UILabel *lblDate = (UILabel*)[cell viewWithTag:101];
UILabel *lblDistance = (UILabel*)[cell viewWithTag:102];
UILabel *lbltype = (UILabel*)[cell viewWithTag:103];
lblDate.text = [temp objectAtIndex:indexPath.row] valueForKey:#"date"] stringByReplacingOccurrencesOfString:#"-" withString:#"/"]];
lblDistance.text = [NSString stringWithFormat:#"%# KM",[[temp objectAtIndex:indexPath.row] valueForKey:#"distance"]];
NSString *type = [NSString stringWithFormat:#"%#",[[temp objectAtIndex:indexPath.row] valueForKey:#"distance"]];
if([type isEqualToString:#"0"])
{
lbltype.text = #"Personal";
}
else
{
lbltype.text = #"Bussiness";
}
// Configure
return cell;
}
I have an app consisting of a TabBar with a few TabBarControllers. One Controller contains a very simple table, which is supposed to display the contents of a NSMutableDictionary. When you hit the appropriate button, the Dictionary is updated in a separate Controller and the view switches to the UITableViewController, displaying the newly updated table.
I can see the Dictionary being updated. But the TableView never reflects the changes. In fact, it seems to display the changes only the 1st time I enter that screen.
I have tried [self table.reloadData] and while it gets called, the changes aren't reflected to the UITableView.
Does anyone have any suggestions? I am happy to post code, but am unsure what to post.
Update: the table is updated and refreshed properly only the 1st time it is displayed. Subsequent displays simply show the original contents.
Background:
The tableview gets filled from a dictionary: appDelegate.currentFave. The tableview should get refreshed each time the ViewController is invoked by the TabBarController.
- (void)viewWillAppear:(BOOL)animated
{
NSLog(#"in viewWillAppear");
[super viewWillAppear:animated];
[self loadFavesFile];
[self.tableView reloadData];
}
// load the Favorites file from disk
- (void) loadFavesFile
{
// get location of file
NSString *path = [self getFavesFilePath];
// The Favorites .plist data is different from the Affirmations in that it will never be stored in the bundle. Instead,
// if it exists, then use it. If not, no problem.
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
// read Faves file and store it for later use...
NSMutableDictionary *tempDict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
appDelegate.sharedData.dictFaves = tempDict;
// grab the latest quote. Append it to the list of existing favorites
NSString *key = [NSString stringWithFormat:#"%d", appDelegate.sharedData.dictFaves.count + 1];
NSString *newFave = [NSString stringWithFormat:#"%#", appDelegate.currentFave];
[appDelegate.sharedData.dictFaves setObject:newFave forKey:key];
} else {
NSLog(#"Favorites file doesn't exist");
appDelegate.sharedData.dictFaves = nil;
}
}
// this gets invoked the very first call. Only once per running of the App.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// reuse or create the cell
static NSString *cellID = #"cellId";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
// allow longer lines to wrap
cell.textLabel.numberOfLines = 0; // Multiline
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.font = [UIFont fontWithName:#"Chalkduster" size:(16)];
cell.textLabel.textColor = [UIColor yellowColor];
// NOTE: for reasons unknown, I cannot set either the cell- or table- background color. So it must be done using the Label.
// set the text for the cell
NSString *row = [NSString stringWithFormat:#"%d", indexPath.row + 1];
cell.textLabel.text = [appDelegate.sharedData.dictFaves objectForKey:row];
return cell;
}
I found the problem. I was not properly initializing and assignng the TableView in my view controller. See below
- (void)viewDidLoad
{
[super viewDidLoad];
tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.delegate = self;
tableView.backgroundColor=[UIColor blackColor];
self.view = tableView;
}
Assuming the code you have put up is correct, you want to use [self.table reloadData]. You have the . in the wrong place.
I had this same problem yesterday, for me it turned out I had set the wrong file owner in interface builder and hadn't set up the data source and delegates for the table view properly.
Try going into interface builder and right-clicking on the file owner, this should show you if anything isn't connected up properly.
You should make sure that your Interface Builder connections are set up properly, but what this problem really sounds like is that you have your UITableViewCell setup code in cellForRowAtIndexPath: inside your if(cell == nil) statement. Which it shouldn't be. Let me explain. If you have a list of cells, and you want to set the titles to each cell to a string in an array called myArray, right now your (incorrect) code looks like this:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellIdentifier"];
if (cell == nil) {
// No cell to reuse => create a new one
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cellIdentifier"] autorelease];
[[cell textLabel] setText:[myArray objectAtIndex:[indexPath row]]];
}
return cell;
}
Can you see the problem with that logic? The cell will only get an updated title if no reusable cell can be found, which, in your case, sounds like the situation. Apple says that you should create a 'new' cell each time cellForRowAtIndexPath: is called, which means that you put all of your setup code outside of the if(cell == nil) check.
Continuing with this example, the proper code would look like this:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellIdentifier"];
if (cell == nil) {
// No cell to reuse => create a new one
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cellIdentifier"] autorelease];
}
[[cell textLabel] setText:[myArray objectAtIndex:[indexPath row]]];
return cell;
}
This way, the cell gets assigned the proper string whether or not a reusable cell is found and so calling reloadData will have the desired effect.
Below is code for UITableView, But when i scroll its behaves weirdly (too annoying)... This problem is due to reuseIdentifier.... but dont know how to solve..
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];
NSInteger imgTag = 1;
NSInteger lblTag = 2;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 52, 52)];
// Image:[UIImage imageNamed:[self.glassType objectAtIndex:indexPath.row]]];
imgView.tag = imgTag;
[cell.contentView addSubview:imgView];
[imgView release];
UILabel *lblName = [[UILabel alloc] initWithFrame:CGRectMake(60, cell.frame.size.height/4, 200, 21)];
// lblName.text = [self.glassName objectAtIndex:indexPath.row];
lblName.tag = lblTag;
[cell addSubview:lblName];
[lblName release];
}
NSInteger imgIndex = 2;
NSInteger lblIndex = 3;
((UIImageView *)[cell viewWithTag:imgTag]).image = [[self.glassType objectAtIndex:indexPath.row] objectAtIndex:imgIndex];
((UILabel *)[cell viewWithTag:lblTag]).text = [[self.glassName objectAtIndex:indexPath.row] objectAtIndex:lblIndex];
return cell;
}
- (void)tableView:(UITableView *)tableView1 didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView1 cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
How to make Cell for row at index so that it remains constant even when scrolled??? Also how to make single selection in UITableView??
The answer is that you should not add subviews to your table cells outside of the "if (cell == nil) { ..." clause or they get added over and over again to the same cell when it gets re-used.
See my answer to this question for a more detailed explanation, including code for how to fix it:
cellForRowAtIndexPath memory management
You also cannot store state in table cells because as soon as they scroll offscreen they are recycled and re-appear at a different index in your table. You need to set up an array of model objects to store state for your table cells (such as what their accessory type should be). A more detailed explanation can be found in my answer to this question:
Looping through UITableViewCells of a UITableView
If you fix how you are adding subviews to the cells, and store your "ticked" state in an array of model objects as well as setting the cell.accessoryType (so that it can be restored when the cell is dequeued), then your approach to row selection is otherwise correct.
So put this in your tableView:cellForRowAtIndexPath: method, just before the return cell;:
MyModelObject *object = [self.arrayOfModelObjects objectAtIndex:indexPath.row];
BOOL isChecked = object.checked;
cell.accessoryType = isChecked? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;
And in your tableView: didSelectRowAtIndexPath: method, get rid of the current logic and replace it with:
- (void)tableView:(UITableView *)tableView1 didSelectRowAtIndexPath:(NSIndexPath *)indexPath
for (int i = 0; i < [self.arrayOfModelObjects count]; i++)
{
MyModelObject *object = [self.arrayOfModelObjects objectAtIndex:i];
object.checked = (i == indexPath.row); // only check the one we just tapped
}
//refresh table to update the accessory views for all rows
[tableView1 reloadData];
}
Obviously replace the arrayOfModelObjects with your own model implementation. You could just use an array of NSNumber objects containing bools if you don't want to create a custom class for this purpose.
The recycling queue is like a pool where previously created Cells are stored before to reuse them. For example when you scrolls up, at the moment the cell disappears above, it is stored in the queue and becomes available for the cell that will appear at the bottom. Ok ?
Actually the number of cells really created is exactly the max simultaneous cell you can display in your table (in most cases from 3 to 8). In other words your if (cell == nil) code is executed (more or less from 3 to 8 times) at the first reloadData to create the pool of cells your table needs.
Then all you make on a cell is kept as it and appears again when you dequeue it. It's now easy to understand that, in your code, you have to make all strictly row-dependant settings outside the if (cell == nil) block. The same way, do not add subViews outside the if (cell == nil) block, you can imagine the thousands of subview you will add each time you reset a dequeued cell !
Tip: if you need some custom cleanup before reusing a cell (like to set an image to blank), you can create a custom UITableviewCell class and implements the prepareForReuse method.
Is it clear ?
Always reload your tableView in viewWillAppear method instead of viewDidLoad.
(void) viewWillAppear:(BOOL)animated{
[self.tableView reloadData];
}
This avoids most of all unexpected and annoying problems. :)
I have been trying to figure out how to set the accessoryType to UITableViewCellAccessoryCheckmark when the cell is selected but am having trouble finding a decent example of this.
If you know how to do this or a good tutorial could you please let me know that would be great.
To restrict the user to just one selection, meaning to create an exclusive list of one choice only, you could follow these steps;
Firstly, have a global index path declared in your .h file to keep track of the already selected cell ->
NSIndexPath *oldIndexPath;
When you create the cells, be sure to set the accessory type to none, so that no cell is selected by default when the table is seen;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CallIdentifier"];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Finally, in the didSelectRowAtIndexPath delegate method, add the following code which will remove the checkmark from the already selected cell, and add a checkmark to the newly selected one.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (oldIndexPath==nil) { // No selection made yet
oldIndexPath=indexPath;
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else {
UITableViewCell *formerSelectedcell = [tableView cellForRowAtIndexPath:oldIndexPath]; // finding the already selected cell
[formerSelectedcell setAccessoryType:UITableViewCellAccessoryNone];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark]; // 'select' the new cell
oldIndexPath=indexPath;
}
}
Hope this works out! :)
Something like this may work:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:myTableView cellForRowAtIndexPath:indexPath];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
To answer the comment below, just push a viewController in the same method like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:myTableView cellForRowAtIndexPath:indexPath];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
// Then push a new view
iPhoneCustomViewController *myVC = [[iPhoneCustomViewController alloc] initWithNibName:#"iPhoneCustomViewController" bundle:nil];
[self.navigationController pushViewController:myVC animated:YES];
[myVC release];
// And deselect the row (if desired)
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Did you know that:
1.) UITableView keeps track of the index paths for the rows that have been selected? It's in an array called indexPathsForSelectedRows
2.) UITableView has a flag you can set to make it either single or multiple selection. You can change it by calling the setter setAllowsMultipleSelection:(BOOL).
So, assuming that the table has been set to single selection, we can do the following in the tableView:CellForRowAtIndexPath method ...
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[[cell textLabel] setText:#"Some Text"];
NSArray *selectedIndexPaths = [tableView indexPathsForSelectedRows];
if ([selectedIndexPaths containsObject:indexPath]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;}
This implementation of CellForRowAtIndexPath will give you a clean checkmark with no gray background when a cell is selected. You will need to set the checkmark in the didSelectRowAtIndexPath delegate method to make sure a cell gets the checkmark the moment it gets selected.
No need to create separate ivars or anything else to keep track of what was or wasn't selected. It's all neatly contained in the UITableView as Apple intended.
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType=UITableViewCellAccessoryCheckmark;
Implement this in didSelectRowAtIndexPath delegate method
From the docs:
The delegate handles selections in this method. One of the things it
can do is exclusively assign the check-mark image
(UITableViewCellAccessoryCheckmark) to one row in a section
(radio-list style). This method isn’t called when the editing property
of the table is set to YES (that is, the table view is in editing
mode). See "Managing Selections" in Table View Programming Guide for
iOS for further information (and code examples) related to this
method.
Here is an example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]
cell.UITableViewAccessoryType = UITableViewCellAccessoryCheckmark;
}