Meredith Caveney Meredith Caveney - 10 days ago 3
Objective-C Question

XCode TableViewController to detail in Objective-C

I have a TabBarController with 4 tabs, 3 of which are table views. I am trying to put a detail for every table view cell, and I don't think storyboard is efficient since I have over 50 detail pages. I'm very new to all of this, and I've tried to find out how to link a detail to every tab for a couple hours. My table views start with the Second View Controller.
Here is SecondViewController.m:

#import "SecondViewController.h"
@implementation SecondViewController
{
NSArray *tableData;
}
@synthesize tableData;

#pragma mark - View lifecycle

- (void)viewDidLoad
{
tableData = [NSArray arrayWithObjects:@"Carter", @"Greene", @"Hancock", @"Hawkins", @"Johnson", @"Sullivan", @"Unicoi", @"Washington", nil];
[super viewDidLoad];

}

#pragma mark - TableView Data Source methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return [tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];

if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
}

cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];


return cell;
}

@end


Here is SecondViewController.h:

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource>

@property(nonatomic, retain) NSArray *tableData;
@end


If this helps, here is my storyboard.

imgur.com/f9xdo0E

If anyone can help me individually add details to each table view cell in the most painless way possible, I would appreciate it. Thanks!

Rob Rob
Answer

If using storyboards, the process is fairly simple.

First, I'd suggest dragging a prototype "table view cell" on to your table views. You can then control-drag from that prototype cell to your destination scene to add a segue between the cell and the next scene:

enter image description here

Make sure to select that prototype cell and set its storyboard identifier (I used "Cell"). You will need to reference that storyboard identifier, as shown in my code sample below. I also configured appearance related things (like the disclosure indicator) right in that cell prototype in IB so I don't have to worry about doing that in code and I can see what the UI will look like right in IB.

Now you can go to the table view controller and (a) simplify cellForRowAtIndexPath (because you don't need that logic about if (cell == nil) ... when using cell prototypes); but also implement a prepareForSegue to pass the data to the destination scene:

//  SecondViewController.m

#import "SecondViewController.h"
#import "DetailsViewController.h"

@interface SecondViewController ()
@property (nonatomic, strong) NSArray *tableData;
@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableData = @[@"Carter", @"Greene", @"Hancock", @"Hawkins", @"Johnson", @"Sullivan", @"Unicoi", @"Washington"];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.destinationViewController isKindOfClass:[DetailsViewController class]]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSString *name = self.tableData[indexPath.row];
        [(DetailsViewController *)segue.destinationViewController setName:name];
    }
}

- (IBAction)unwindToTableView:(UIStoryboardSegue *)segue {
    // this is intentionally blank; but needed if we want to unwind back here
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.tableData.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    cell.textLabel.text = self.tableData[indexPath.row];

    return cell;
}

@end

Obviously, this assumes that you created a DetailsViewController and specified it as the destination scene's base class, and then create properties for any values you want to pass to this destination scene:

//  DetailsViewController.h

#import <UIKit/UIKit.h>

@interface DetailsViewController : UIViewController

@property (nonatomic, copy) NSString *name;

@end

And this destination scene would then take the name value passed to it and fill in the UILabel:

//  DetailsViewController.m

#import "DetailsViewController.h"

@interface DetailsViewController ()

@property (weak, nonatomic) IBOutlet UILabel *nameLabel;

@end

@implementation DetailsViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.nameLabel.text = self.name;
}

@end

Frankly, this process will undoubtedly be described more clearly in any UITableView tutorial includes a discussion of "cell prototypes" (your code sample suggests you were using an older tutorial that predates cell prototypes).

Comments