So I've found many questions and answers on this issue but I still dont seem to be able to fix my issue.
I've got this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if(tableView == self.moduleTableView){
UITableViewCell *cell = [_moduleTableView dequeueReusableCellWithIdentifier:#"TableIDCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"TableIDCell"];
}
Thats all fine and works for the moduleTableView and I have code to fill the individual cells.
However, I later have an if(tableView == theOtherTableview) and the code is never executed, (have used break points to check). Because of this the second tableview never loads and fills.
I've done for the same if statements in the numberOfRows method and I declare:
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
self.otherTblEvents.delegate = self;
self.otherTblEvents.dataSource = self;
and it still doesn't work, am I missing anything? I think I've linked the implementation correctly to the storyboard, I just can't get it to reload the cellForRowAtIndexPath: method while (tableView == OtherTableView)
Thanks
I had the exact same issue as you.
I found that the cleanest solution is to make 2 datasource classes. That way there is alot less code in your view controller.
Basically something like this
DatasourceTblEvents *ds1 = [DatasourceTblEvents new];
DatasourceotherTblEvents *ds2 = [DatasourceotherTblEvents new];
self.tblEvents.dataSource = ds1;
self.otherTblEvents.dataSource = ds2;
This dramatically reduces the amount of if statements within the datasource protocol methods. And this way you can just implement the datasource methods in each datasource class like you would with one table view.
Hope this helps.
Check if - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section method returns zero value (empty array count), Cell for Row Method will be called only if numberOfRowsInSection method returns non zero value.
numberOfRowsInSection should return a non zero value
Related
I am using a custom cell class in a tableview controller.
When I include a statement in the tableviewcontroller in cellForRowAtIndexPath NSLog(#"method called"): it does not seem to get called.
Is it possible that this method is not called when you have a custom cell?
Edit:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell for row at index path called");
NSDictionary *item= [self.getItems objectAtIndex:indexPath.row];
//This sets place in storyboard VC
IDTVCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.item = item;
if (cell == nil) {
cell = [[IDTVCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"];
}
return cell;
}
cellForRowAtIndexPath is not called if no rows are returned.
-tableView:cellForRowAtIndexPath: is not getting called
That is what happened in my case.
It can also not get returned if you reload table on wrong thread and in certain other scenarios.
cellForRowAtIndexPath: not called
However, a custom cell per se does not cause this..
To answer your question - Yes, it is.
There could be n-number of reasons why cellForRowAtIndexPath: is not getting called. This may be because delegate / dataSource is not set or UITableView frame is not set... etc. etc.
You should easily find a solution with more online research and closure look at your code.
I am trying to reduce duplicate code when laying out my tableview but running into lifecycle problems. Basically its that heightFroRowAtIndexPath is called before cellForRowAtIndexPath. Which is what should happen and I understand why.
But...
I have a cell that is laid out in a storyboard. It has an optional field. If the optional field is not in the data then I remove a label for that field. However I am removing that label in a custom cell implementation:
CustomCell (extends UITableViewCell)
- (void) configureCellForData: (Data *) data {
if (data.optional) {
self.optionalLabel.text = [data.optional];
} else {
[self.optionalLabel removeFromSuperview];
}
}
Then in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:self.tableLayout[indexPath.section][indexPath.row]];
[cell configureCellForData:self.data];
return cell;
}
Which works great for setting up the cell. However the height is wrong if the optional field is removed, ie I need to adjust if the optional field was removed.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:self.tableLayout[indexPath.section][indexPath.row]];
CustomCell *headerCell = (CustomCell *) cell;
if (self.data.optional == nil) {
return cell.bounds.size.height - headerCell.optionalLabel.bounds.size.height;
}
return cell.bounds.size.height;
}
}
It does not seem like much but I simplified my check to "data.optional == nil" and it is more complex than that and involves a DB call.
Is there a better way to set this up such that I don't have to make the check twice once when the height for cell is calculated and once when the cell is initialized?
If you wanted to only check once you could store an array of booleans that stores whether or not the data is there or not. So, make the check for each row, store the result into the array, before you make the check next time, check to see if the array has an value for that cell, if it does, use that value, if not, make the database call.
Make sure that you only store values in the array index associated with the indexPath, and if the array is shorter than the indexPath you're at, you know you need to make the call and add the value into the array.
Edit: As I think more about it, I would put the bool value on the cell itself, and then just call cell.isDataAvailable (or whatever you want the value to be) in order to avoid the second call when you go to set the cell up, as you would have already checked this in heightForRowAtIndexPath.
I am a beginner in Objective-C & iPhone development.
I add dynamically cells in a TableView. I want to set labels's text properties with an array. I saw many tutorials, and I searched during several hours but labels are never filled.
My code is :
- (void)insertNewObject
{
for (NSInteger ic=0; ic<((pages.count)); ++ic) {
NSLog(#"%d", ic);
NSDictionary *monDico = pages[ic];
menu = [monDico objectForKey:#"Name"];
NSIndexPath *indexPathTable = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPathTable] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; // I try include & exclude : never call
}
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = menu[indexPath.row];
NSLog(#"%#%#", #"Cell Label = ", cell.textLabel.text);
return cell;
}
Please note that insertNewObject method is called during viewDidLoad execution.
I use a breakpoint in the cellForRowAtIndexPath method : it never calls ! I try with :
explicit calling
forcing reloadData method
but did not work too.
Can you please tell me why ?
Thanks in advance.
If cellForRowAtIndexPath is not being called then most likely you have not set:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [menu count]; // indicates the number of rows in your table view
}
This method needs to return the number of rows you expect to render within your table view. The default is 0 = no rows. I'm assuming you want to show all the items in your menu array so simply return [menu count].
Check this: UITableViewDataSource Protocol Reference
If you want to access to textLabel property of your cell, then it must be style of: UITableViewCellStyleDefault. Or, if you use storyboard, then set Cell's style to Basic.
And, of course, make sure that you have set delegate and datasource properties of your tableView.
- (void)viewDidLoad
{
[super viewDidLoad];
//...
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
------------------EDIT------------------
If you're using UITableViewController, then no more need to set delegate and dataSource properties manually, because they will automatically set by UITableViewController when your view did load.
If cellForRowAtIndexPath: method still not being called, then make sure that following methods that you implemented, both returns value >0:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
and
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Set a breakpoint before return and see returning values, or just NSLog them before returning.
I'm really new to Objective-C here so what I'm asking may be trivial to most of you but any guidance will help.
Here's a picture of my storyboad.
My current objective is to allow for the user to enter in the number of sets (NSInteger *numReps) and then press the "Log Reps" button and have the table initialize with numReps cells that look like the prototype cell.
Now where I'm at a loss for the implementation. I've never done this kind of thing before so I'm not exactly sure what the best way to go about it is. I have thought of making a custom class for the UITableView table that would take info from the view after the Log Reps button is pushed. I'm not entirely sure how this would need to be implemented. Or can I simply add the table to the properties of the view controller and setup the table within the view controller? That was my initial idea and seems ideal so that I would have everything in one place.
Pleas advise. I am new to all of this and come from a C++ background so I'm still learning a lot of the notation.
Try this:
-(IBAction)btnLogClicked {
int iSet = 4 //Number of row in table
UITableView *tblView= [[UITab;eView alloc]initWithFrame:CGRectMake(0,50,320,100)];
tblView.delegate = self;
tblView.dataSource = self;
[self.view addSubView:tblView];
}
Table View Data Source and Delegate Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return iSet;
}
- (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];
}
// Display what you want to display in each cell
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
It's not clear what you want to present in your prototype cells, but you need an array (or probably an array of dictionaries) to populate the cells. The number of rows is determined by the number of entires (the count) of that array. So, if you take the number entered by the user, and add that many object to your array, then call reloadData on the table, you will get the number of rows that you want. What those object are that you add to the array, depends on what you're trying to show there.
you could start reading: Table View Programming Guide for iOS
But I can answer you:
You can add the UITableView to the UIViewController, but you need set your UIViewController like the TableView's delegate and dataSource. Your ViewController need to implement the protocol: UITableViewDataSource
The method that you are looking for is: tableView:numberOfRowsInSection:
But I really recommend you that read the Apple Reference.
When parsing a local XML file i can see the data in console using NSLog. While in the simulator am getting only the plain table view without any data parsed from xml. Am not understanding where am missing it.
- (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];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
theLists = [app.listArray objectAtIndex:indexPath.row];
cell.textLabel.text = theLists.title;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
I think you are not reloading your table view.
after completing your parsing just reload your table view.
[reload tablename];
then check your table view delegates are calling or not after this method.
I think this will help you.
happy coding.
It seems you are reloading in the DidLoad.But After parsing and getting the data from xml, You have to reload that data with TableView.
[yourtableView reloadData];
Before doing thing, be sure that you have set Delegate and DataSource.
I think there are two expected reasons for that:
1- May be the number of sections and number of row are not set with the correct value.
2- may be you need to reload the table view data.
Please check these two methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5; // or any number you want
}
I got the answer finally where i didn't properly connected the tableview controller class with corresponding controller. I followed the link Trouble making connections with story board
And finally it showed the data in the table view.
Hope this answer might help others. Thanks for all the people who gave their suggestions in this post.
Figured I should add this, if you are having trouble with data not showing up or loading.
Make sure your tableview delegate and data source are set to self.
So in the viewcontroller's viewDidLoad() function, make sure you add
tableView.delegate = self
tableView.dataSource = self