0

I am writing an app in XCode6. Currently I have "SelectionTableViewController.h" and "SelectionTableViewController.m" such that you could add/remove checkmarks on select. Also, I have a table view controller segue in the storyboard, that is triggered by a static cell in the previous table view controller. I set up the trigger in storyboard so I did not write the code for "prepare for segue" or anything. I want the cell to be checked by default, so I have done the following:

  • Changed the view controller to "SelectionTableViewController"
  • Set the identifier of prototype cell on my storyboard to "SelectionCell"
  • Changed the cell's background color to orange and accessory to checkmark

Below is my SelectionTableViewController.m:

@implementation SelectionTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:[UITableViewCell class]
           forCellReuseIdentifier:@"SelectionCell"];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO];
    self.navigationItem.title = @"Select";
    [self.tableView reloadData];
}

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

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return [[[MyStore sharedStore] allCategories] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    NSString *category = [[[MyStore sharedStore] allCategories] objectAtIndex:section];
    return [[[MyStore sharedStore] allNamesForCategory: category] count];
}


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

    // Configure the cell...
    NSString *category = [[[MyStore sharedStore] allCategories] objectAtIndex:indexPath.section];
    NSArray *items = [[MyStore sharedStore] allNamesForCategory: category];

    cell.textLabel.text = [items objectAtIndex:indexPath.row];

    return cell;
}
#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
    } else {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [[[MyStore sharedStore] allCategories] objectAtIndex:section];
}

@end

My program runs on the simulator, and the items listed in the cells are correct. However the cells does not have the default checkmark on the cell before I do a selection. Nor are the cells orange. I know I can set up the default checkmark and the background color in code easily, but I just want to figure out how to do this in the interface builder, as I would be dealing with the UI a lot when the program is set up.

Hope someone can help me on that as I'm kinda new to iOS programming and this is the first time I have ever used Storyboard. Thanks!

2 Answers2

1

The problem with your implementation is tableView:didSelectRowAtIndexPath will only be triggered by user's interaction only, therefore the initial selection doesn't show. You will need to make tableView aware of the selection state during initialisation too, else de-selection will not function as expected.

class ViewController: UITableViewController {

    var selectedItem: Int = 5

    func updateSelection(selected: Bool, forCell cell: UITableViewCell) {
        cell.accessoryType = selected ? .Checkmark : .None
        // update other cell appearances here..
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        // Note: happens after the initial tableView.reloadData()
        // Let tableView know who's selected before we appear, so that tableView is aware of the selection state.
        // Doing so will enable tableView to know which cell to deselect after a new selection.
        tableView.selectRowAtIndexPath(NSIndexPath(forItem: selectedItem, inSection: 0), animated: true, scrollPosition: .Middle)
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
        cell.textLabel?.text = "Item \(indexPath.item)"
        // Setup the selection appearance during cell creation
        updateSelection(indexPath.item == selectedItem, forCell: cell)
        return cell
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // Keep track of the selection, and update cell appearance
        selectedItem = indexPath.item
        updateSelection(true, forCell: tableView.cellForRowAtIndexPath(indexPath)!)
    }

    override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
        // As above
        updateSelection(false, forCell: tableView.cellForRowAtIndexPath(indexPath)!)
    }

}
Ivan Choo
  • 1,997
  • 15
  • 15
0

I've figured it out myself! I deleted the code that registered "Selection Cell". Then I did some minor changes to the cellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath(NSIndexPath*)indexPath
{
    Static NSString *selectionCell = @"SelectionCell"; 
    UITableViewCell *cell=[tableViewdequeueReusableCellWithIdentifier:selectionCell forIndexPath:indexPath];

    // Omit...
}