UITableViewCell - check mark retained for selected

2019-09-07 16:27发布

问题:

This is a follow-up question to UITableViewCell - check mark one row per section. Here I have 2 sections with 3 rows each as follow:

  1. SEARCH DISTANCE

    • 250 feet

    • 1000 feet

    • 4000 feet

  2. MAP TYPE

    • Standard

    • Satellite

    • Hybrid

I have a problem in section2(MAP TYPE). I want to have 'standard' checked as default and whatever option user chooses later on can be saved and passed on to another view controller which contains map view to display according to map type selected. My current code does not allow me to do so for section2. Anyone, please help check my code and suggest me what need to be added/modified?

I've been trying to learn how it works for section1(SEARCH DISTANCE) but I just don't quite get it. It seems to involve delegate file to do cache things.

Here my code is:

#import "PAWSettingsViewController.h"

#import "PAWAppDelegate.h"
#import <Parse/Parse.h>

@interface PAWSettingsViewController ()

- (NSString *)distanceLabelForCell:(NSIndexPath *)indexPath;
- (PAWLocationAccuracy)distanceForCell:(NSIndexPath *)indexPath;

- (NSString *)maptypeLabelForCell:(NSIndexPath *)indexPath;  
- (PAWMaptypeSelect)maptypeForCell:(NSIndexPath *)indexPath;

@property (nonatomic, assign) CLLocationAccuracy filterDistance;

@end

typedef enum {
    kPAWSettingsTableViewDistance = 0,
    kPAWSettingsTableViewMaptype,
    kPAWSettingsTableViewNumberOfSections
} kPAWSettingsTableViewSections;

typedef enum {
    kPAWSettingsTableViewDistanceSection250FeetRow = 0,
    kPAWSettingsTableViewDistanceSection1000FeetRow,
    kPAWSettingsTableViewDistanceSection4000FeetRow,
    kPAWSettingsTableViewDistanceNumberOfRows
} kPAWSettingsTableViewDistanceSectionRows;

typedef enum {
    kPAWSettingsTableViewMaptypeSectionStandardRow = 0,
    kPAWSettingsTableViewMaptypeSectionSatelliteRow,
    kPAWSettingsTableViewMaptypeSectionHybridRow,
    kPAWSettingsTableViewMaptypeNumberOfRows
} kPAWSettingsTableViewMaptypeSectionRows;

@implementation PAWSettingsViewController

@synthesize tableView;
@synthesize filterDistance;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        PAWAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
        self.filterDistance = appDelegate.filterDistance;
    }
    return self;
}

#pragma mark - Custom setters

// Always fault our filter distance through to the app delegate. We just cache it locally because it's used in the tableview's cells.
- (void)setFilterDistance:(CLLocationAccuracy)aFilterDistance {
    PAWAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    appDelegate.filterDistance = aFilterDistance;
    filterDistance = aFilterDistance;
}

#pragma mark - View lifecycle

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Private helper methods

- (NSString *)distanceLabelForCell:(NSIndexPath *)indexPath {
    NSString *cellText = nil;
    switch (indexPath.row) {
        case kPAWSettingsTableViewDistanceSection250FeetRow:
            cellText = @"250 feet";
            break;
        case kPAWSettingsTableViewDistanceSection1000FeetRow:
            cellText = @"1000 feet";
            break;
        case kPAWSettingsTableViewDistanceSection4000FeetRow:
            cellText = @"4000 feet";
            break;
        case kPAWSettingsTableViewDistanceNumberOfRows: // never reached.
        default:
            cellText = @"The universe";
            break;
    }
    return cellText;
}

- (PAWLocationAccuracy)distanceForCell:(NSIndexPath *)indexPath {
    PAWLocationAccuracy distance = 0.0;
    switch (indexPath.row) {
        case kPAWSettingsTableViewDistanceSection250FeetRow:
            distance = 250;
            break;
        case kPAWSettingsTableViewDistanceSection1000FeetRow:
            distance = 1000;
            break;
        case kPAWSettingsTableViewDistanceSection4000FeetRow:
            distance = 4000;
            break;
        case kPAWSettingsTableViewDistanceNumberOfRows: // never reached.
        default:
            distance = 10000 * kPAWFeetToMiles;
            break;
    }
    return distance;
}

- (NSString *)maptypeLabelForCell:(NSIndexPath *)indexPath {
    NSString *cellText = nil;
    switch (indexPath.row) {
        case kPAWSettingsTableViewMaptypeSectionStandardRow:
            cellText = @"Standard";
            break;
        case kPAWSettingsTableViewMaptypeSectionSatelliteRow:
            cellText = @"Satellite";
            break;
        case kPAWSettingsTableViewMaptypeSectionHybridRow:
            cellText = @"Hybrid";
            break;
        case kPAWSettingsTableViewMaptypeNumberOfRows: // never reached.
        default:
            cellText = @"?";
            break;
    }
    return cellText;
}

- (PAWMaptypeSelect)maptypeForCell:(NSIndexPath *)indexPath {
    PAWMaptypeSelect maptype = nil;
    switch (indexPath.row) {
        case kPAWSettingsTableViewMaptypeSectionStandardRow:
            maptype = @"Standard";
            break;
        case kPAWSettingsTableViewMaptypeSectionSatelliteRow:
            maptype = @"Satellite";
            break;
        case kPAWSettingsTableViewMaptypeSectionHybridRow:
            maptype = @"Hybrid";
            break;
        case kPAWSettingsTableViewMaptypeNumberOfRows: // never reached.
        default:
            maptype = nil;
            break;
    }
    return maptype;
}

#pragma mark - UINavigationBar-based actions

- (IBAction)done:(id)sender {
    [self.presentingViewController dismissModalViewControllerAnimated:YES];
}

#pragma mark - UITableViewDataSource methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return kPAWSettingsTableViewNumberOfSections;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    switch ((kPAWSettingsTableViewSections)section) {
        case kPAWSettingsTableViewDistance:
            return kPAWSettingsTableViewDistanceNumberOfRows;
            break;
        case kPAWSettingsTableViewMaptype:
            return kPAWSettingsTableViewMaptypeNumberOfRows;
            break;
        case kPAWSettingsTableViewNumberOfSections:
            return 0;
            break;
    };
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"SettingsTableView";
    if (indexPath.section == kPAWSettingsTableViewDistance) {
        UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];
        if ( cell == nil )
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:identifier];
        }

        // Configure the cell.
        cell.tag = indexPath.section;
        cell.textLabel.text = [self distanceLabelForCell:indexPath];

        if (self.filterDistance == 0.0) {
            NSLog(@"We have a zero filter distance!");
        }

        PAWLocationAccuracy filterDistanceInFeet = self.filterDistance * ( 1 / kPAWFeetToMeters);
        PAWLocationAccuracy distanceForCell = [self distanceForCell:indexPath];
        if (abs(distanceForCell - filterDistanceInFeet) < 0.001 ) {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        } else {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }

        return cell;
    } else if (indexPath.section == kPAWSettingsTableViewMaptype){
        UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];
        if ( cell == nil )
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:identifier];
        }

        // Configure the cell.
        cell.tag = indexPath.section;
        cell.textLabel.text = [self maptypeLabelForCell:indexPath];
        //**** I don't know how to do here? ****
        return cell;
    } else {
        return nil;
    }
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    switch ((kPAWSettingsTableViewSections)section) {
        case kPAWSettingsTableViewDistance:
            return @"Search Distance";
            break;
        case kPAWSettingsTableViewMaptype:
            return @"Map Type";
            break;
        case kPAWSettingsTableViewNumberOfSections:
            return @"";
            break;
    }
}

#pragma mark - UITableViewDelegate methods

// Called after the user changes the selection.
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == kPAWSettingsTableViewDistance) {
        [aTableView deselectRowAtIndexPath:indexPath animated:YES];

        // if we were already selected, bail and save some work.

        UITableViewCell *selectedCell = [aTableView cellForRowAtIndexPath:indexPath];
        if (selectedCell.accessoryType == UITableViewCellAccessoryCheckmark) {
            return;
        }

        // uncheck all visible cells.

        for (UITableViewCell *cell in [aTableView visibleCells]) {
            if (cell.accessoryType != UITableViewCellAccessoryNone && cell.tag == indexPath.section) {
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
        }
        selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;

        PAWLocationAccuracy distanceForCellInFeet = [self distanceForCell:indexPath];
        self.filterDistance = distanceForCellInFeet * kPAWFeetToMeters;
    }
    else if (indexPath.section == kPAWSettingsTableViewMaptype){
        [aTableView deselectRowAtIndexPath:indexPath animated:YES];

        // if we were already selected, bail and save some work.

        UITableViewCell *selectedCell = [aTableView cellForRowAtIndexPath:indexPath];
        if (selectedCell.accessoryType == UITableViewCellAccessoryCheckmark) {
            return;
        }

        // uncheck all visible cells.

        for (UITableViewCell *cell in [aTableView visibleCells]) {
            if (cell.accessoryType != UITableViewCellAccessoryNone && cell.tag == indexPath.section) {
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
        }

        selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;

        //**** I don't know how to do here? ****
    }

}

@end

回答1:

Use an bool variable. Like isFirstTime.

and then in viewDidLoad: initilize your isFirstTime variable as YES.

isFirstTime = YES;

in your

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

update this part

else if (indexPath.section == kPAWSettingsTableViewMaptype){
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];
    if ( cell == nil )
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:identifier];
    }
    if ( isFirstTime == YES && indexPath.row == 0)
    {

    }        // Configure the cell.
    cell.tag = indexPath.section;
    cell.textLabel.text = [self maptypeLabelForCell:indexPath];
    //**** I don't know how to do here? ****
    return cell;
}


回答2:

I have figured out my own question. I decided to go for global variable to save selected choice in section2. I declared global variable in .m file:

int gmaptypeSelected;

In cellForRowAtOIndexPath section I put a condition like this:

else if (indexPath.section == kPAWSettingsTableViewMaptype){
        UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:identifier];
        if ( cell == nil )
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:identifier];
        }


    // Configure the cell.
    cell.tag = indexPath.section;
    cell.textLabel.text = [self maptypeLabelForCell:indexPath];

    MKMapType maptypeForCell = [self maptypeForCell:indexPath];
    if (maptypeForCell == gmaptypeSelected) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

And in MapView Controller > viewWillAppear will look like this:

- (void)viewWillAppear:(BOOL)animated {

    extern int gmaptypeSelected;
    if (gmaptypeSelected == 0) {
        self.mapView.mapType = MKMapTypeStandard;
    } else if (gmaptypeSelected == 1) {
        self.mapView.mapType = MKMapTypeSatellite;
    } else if (gmaptypeSelected == 2) {
        self.mapView.mapType = MKMapTypeHybrid;
    }

    [locationManager startUpdatingLocation];
    [super viewWillAppear:animated];
}