I have an application in Xcode 4.6 which uses storyboards. I added a UITableView to a view controller class, which worked as expected. However, when I tried deleting the UITableView in the storyboard and adding it back into the same class programmatically, I ran into two specific problems:
1) Although I set the UITableViewCell type to be of type subtitle, the detail label no longer appears.
2) The segue that should occur when I select a cell does not occur, and prepare segue is not even being called, indicating that no message is being sent to the table view when a cell is selected.
Here is the relevant code:
@interface StatsTableViewController () <UITableViewDataSource, UITableViewDelegate> @property (strong, nonatomic) UITableView *tableView; @end @implementation StatsTableViewController -(UITableView *)makeTableView { CGFloat x = 0; CGFloat y = 50; CGFloat width = self.view.frame.size.width; CGFloat height = self.view.frame.size.height - 50; CGRect tableFrame = CGRectMake(x, y, width, height); UITableView *tableView = [[UITableView alloc]initWithFrame:tableFrame style:UITableViewStylePlain]; tableView.rowHeight = 45; tableView.sectionFooterHeight = 22; tableView.sectionHeaderHeight = 22; tableView.scrollEnabled = YES; tableView.showsVerticalScrollIndicator = YES; tableView.userInteractionEnabled = YES; tableView.bounces = YES; tableView.delegate = self; tableView.dataSource = self; return tableView; } - (void)viewDidLoad { [super viewDidLoad]; self.tableView = [self makeTableView]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"newFriendCell"]; [self.view addSubview:self.tableView]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"newFriendCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } Friend *friend = [self.fetchedResultsController objectAtIndexPath:indexPath]; **//THIS DATA APPEARS** cell.textLabel.text = friend.name; cell.textLabel.font = [cell.textLabel.font fontWithSize:20]; cell.imageView.image = [UIImage imageNamed:@"icon57x57"]; **//THIS DATA DOES NOT APPEAR** cell.detailTextLabel.text = [NSString stringWithFormat:@"%i Games", friend.gameCount]; cell.detailTextLabel.textColor = [UIColor lightGrayColor]; return cell; } -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { [self performSegueWithIdentifier:@"detailsView" sender:self]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { //I set the segue identifier in the interface builder if ([segue.identifier isEqualToString:@"detailsView"]) { NSLog(@"segue"); //check to see if method is called, it is NOT called upon cell touch NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; ///more code to prepare next view controller.... } }
I am not sure what I am forgetting to do so that I can solve these two issues. Any help is appreciated.
Tableiw is a simple list, which displays single-dimensional rows of data. It's smooth because of cell reuse and other magic. 2. UICollectionView is the model for displaying multidimensional data .
UITableView manages the basic appearance of the table, but your app provides the cells ( UITableViewCell objects) that display the actual content. The standard cell configurations display a simple combination of text and images, but you can define custom cells that display any content you want.
Overview. Table views manage only the presentation of their data; they don't manage the data itself. To manage the data, you provide the table with a data source object — an object that implements the UITableViewDataSource protocol. A data source object responds to data-related requests from the table.
When you register a class, and use dequeueReusableCellWithIdentifier:forIndexPath:, the dequeue method is guaranteed to return a cell, so your if (cell == nil) clause is never entered. So, just do it the old way, don't register the class, and use dequeueReusableCellWithIdentifier:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"newFriendCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } //etc. return cell; }
As for the segue, it can't be called because you can't make a segue to a table that you've created in code, not in IB. Again, go back to the old way and use tableView:didSelectRowAtIndexPath: which will be called when you select a cell. Instantiate your detail controller there and do the trasition in code.
After edit:
I didn't see your added code there. You've implemented didDeselectRowAtIndexPath rather than didSelectRowAtIndexPath. If you change that, your segue should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With