简体   繁体   中英

UITableViewController will not call cellForRowAtIndexPath BUT numberOfSectionsInTableView and numberOfRowsInSection are indeed set properly

#import "AssignmentsViewController.h"
#import "Assignment.h"

@interface AssignmentsViewController ()

@property NSMutableArray *assignments;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end

@implementation AssignmentsViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    NSLog(@"viewDidLoad");
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.assignments = [[MySingleton sharedMySingleton] assignments];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
}

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"viewWillAppear");
    [self.tableView reloadData];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    NSLog(@"numberOfSectionsInTableView");
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSLog(@"numberOfRowsInSection");
    return [self.assignments count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"cellForRowAtIndexPath");
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AssignmentCell"];
    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"AssignmentCell"];
    }
    cell.textLabel.text = [[self.assignments objectAtIndex:indexPath.row] title];
    return cell;
}

@end

Console output when the AssignmentsViewController is loaded and at least one homework assignment is in the assignments array:

2013-11-06 18:55:09.396 Homework Planner[4756:70b] viewDidLoad
2013-11-06 18:55:09.403 Homework Planner[4756:70b] numberOfSectionsInTableView
2013-11-06 18:55:09.405 Homework Planner[4756:70b] numberOfRowsInSection
2013-11-06 18:55:09.408 Homework Planner[4756:70b] viewWillAppear
2013-11-06 18:55:09.409 Homework Planner[4756:70b] numberOfSectionsInTableView
2013-11-06 18:55:09.409 Homework Planner[4756:70b] numberOfRowsInSection

I am making an application that displays the users homework assignments. For some reason, cellForRowAtIndexPath is never called, even when I am sure the assignments array has a homework assignment object in it. The homework assignments are added to the array by a modal view, and I have verified that they are indeed added by that process and after the user taps "cancel" the view returns to the view defined by this class. When that happens the other two methods related to the UITableView run, but not cellForRowAtIndexPath. Please help me solve this problem I am having.

Let me contribute one more culprit: "Memory management issue".

If TableView's DataSource object is not kept (retain count is zero) while TableView is pulling data from it, then, suprisingly, tableView:cellForRowAtIndexPath: is not called although numberOfSections and numberOfRows do just get called

Check to see if [self.assignments count] is returning 0 (check if self.assignments is nil .

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSLog(@"[self.assignments count] = %d", [self.assignments count]);
}

Otherwise, the only other reason I can think of right now, is when height returned by delegate method is 0 (in case you are implementing it, otherwise default implementation always give non-zero height so no issue in that case.)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  CGFloat height = 0;
  // Some calculation to determine height of row/cell.

  return height;
}

If cellForRowAtIndexPath is not call it's because the view is not yet rendered on the screen (not drawed), so the system is not able to know the size of the Cell or the UITableView.

To solve that issue make sure that you add your items AFTER the view if rendered (and dimension are known). It can happen if the UITableView is added in a parent view to build complex screen.

If you don't load the data during the init phase, you can call reloadData after setting the data.

Example:

OfferTableViewController * offerList = [[OfferTableViewController alloc] init];

// add the view in the parent view to make sure that the dimension are calculated
[fullSiteView.offersView addSubview: offerList.view]; 
offerList.delegate = self;
// Set the data
offerList.offers = product.offers;
// Force reload to render
[offerList.tableView reloadData];

In addition, if you overwrite heightForRowAtIndexPath make sure that it's return something > 0

Note that even if numberOfRowsInSection and numberOfSectionsInTableView return the right count of items, if the size of the table is unknown, the system will no call cellForRowAtIndexPath

Another problem might be the frame of the tableview itself either having a size of 0 or being offscreen...

I was stuck for ages watching logs of numberOfRowsInSection: being called and heightForRowAtIndexPath: being called and returning a hardcoded value but cellForRowAtIndexPath: was never called!

Try logging out the frame of the tableView, or setting a background colour on it to check its actually viewable on-screen.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM