I'm trying to allow only one UITableViewCell to be checked at a time in a section. What I'm going for is to uncheck a checked UITableViewCell (if there is one) and checking the current selected cell. So basically, If one CellA is selected, and I select CellB, I want CellA to unselect and CellB to select.
Here's what I've done to try and accomplish this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(![self.selectedIndexPaths containsObject:indexPath]) {
[self.selectedIndexPaths addObject:indexPath];
}
else {
[self.selectedIndexPaths removeObject:indexPath];
}
if (indexPath.section == 0) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
else if (indexPath.section == 1) {
if (![self.selectedIndexPaths containsObject:indexPath]) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
else {
for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
if (indexPath2.section == 1) {
[tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden = YES;
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
}
}
}
else if (indexPath.section == 2) {
if (![self.selectedIndexPaths containsObject:indexPath]) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
else {
for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
if (indexPath2.section == 2) {
[tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden = YES;
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
}
}
}
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
if ([tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == YES) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
else {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = YES;
}
}
else if (indexPath.section == 1) {
if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == YES) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
else if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == NO){
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = YES;
}
else {
for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
if (indexPath2.section == 1 && [tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden == YES) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
}
}
}
else if (indexPath.section == 2) {
if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == YES) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
else if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == NO){
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = YES;
}
else {
for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
if (indexPath2.section == 2 && [tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden == YES) {
[tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
}
}
}
}
}
As you can see, I have three sections, and the first one the user can select however many cells they want, but in the second and third, it's limited to one.
The Issue: Whenever I select a cell and then another cell, it works. If I select the first cell, both of them are now checked.
I would appreciate any help or suggestions. Thanks!
Your code looks a lot more complicated than it needs to be. I would do it by creating a property (of type NSIndexPath) for sections 1 and 2, and an array property for section 0 to keep track of the selected cell or cells in the respective sections. Set the value of the properties with the indexPath, or add the indexPath in the case of the array, when a cell is tapped (or delete it if it's already checked). Then check the state of those properties or array in cellForRowAtIndexPath.
#interface TableController ()
#property (strong,nonatomic) NSArray *theData;
#property (strong,nonatomic) NSIndexPath *selectedPathForSection1;
#property (strong,nonatomic) NSIndexPath *selectedPathForSection2;
#property (strong,nonatomic) NSMutableArray *selectedPaths;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
self.selectedPaths = [NSMutableArray new];
self.selectedPathForSection1 = nil;
self.selectedPathForSection2 = nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.theData[indexPath.section][indexPath.row];
if ([self.selectedPathForSection1 isEqual:indexPath] || [self.selectedPathForSection2 isEqual:indexPath] || [self.selectedPaths containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
switch (indexPath.section) {
case 0:
if (! [self.selectedPaths containsObject:indexPath]) {
[self.selectedPaths addObject:indexPath];
}else{
[self.selectedPaths removeObject:indexPath];
}
break;
case 1:
if (![self.selectedPathForSection1 isEqual:indexPath]) {
self.selectedPathForSection1 = indexPath;
}else{
self.selectedPathForSection1 = nil;
}
break;
case 2:
if (![self.selectedPathForSection2 isEqual:indexPath]) {
self.selectedPathForSection2 = indexPath;
}else{
self.selectedPathForSection2 = nil;
}
break;
}
[tableView reloadData];
}
Related
I'm trying to set the title and display a button in my custom cell object in my second table view controller, but only my first dynamic prototype cell is displaying text.
The first prototype cell is UITableViewCell and the second is the custom object. In my first view controller I implement almost the same exact method and it works completely fine. Not sure where my error could be, the models I use have all their data in them. I have the correct cell identifier in my storyboard, and the connection from custom cell to the UIButton is set.
Thanks in advance.
Method:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
static NSString *QuestionSectionIdentifier = #"QuestionSectionCell";
if (indexPath.section == 0)
{
UITableViewCell *cellQuestion = [tableView
dequeueReusableCellWithIdentifier:QuestionSectionIdentifier];
if (cellQuestion == nil) {
cellQuestion = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:QuestionSectionIdentifier];
}
if (indexPath.row == 0) {
cellQuestion.textLabel.text = _headerQuestion.question;
NSLog(#"question here %#", cellQuestion.textLabel.text);
}
return cellQuestion;
}
else
{
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (indexPath.section == 1)
{
if (indexPath.row == 0)
{
[cell.firstButton setTitle:_headerQuestion.questionAuthor.fullName forState:UIControlStateNormal];
[cell.firstButton setTag:_headerQuestion.questionAuthor.userID];
[cell.answerLabelField setHidden:YES];
NSLog(#"section 1 %#", cell.firstButton.titleLabel.text);
}
}
else if (indexPath.section == 2)
{
Answer* answer_num = [_headerQuestion.answers objectAtIndex:indexPath.row]; //object at index
[cell.firstButton setTitle:answer_num.answerAuthor.fullName forState:UIControlStateNormal];
[cell.firstButton setTag:answer_num.answerAuthor.userID];
cell.answerLabelField.text = answer_num.answer;
}
return cell;
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 3;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
{
return 1;
}
if (section == 1)
{
return 1;
}
else
{
return [_headerQuestion.answers count];
}
}
Make sure you register both reuse identifiers with the tableview using
- (void)registerClass:(Class nullable)cellClass
forCellReuseIdentifier:(NSString * nonnull)identifier
Or registerNib if you have a nib for the cell.
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:
SEARCH DISTANCE
250 feet
1000 feet
4000 feet
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
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;
}
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];
}
I have 2 sections and 3 rows each as follow:
SEARCH DISTANCE
250 feet
1000 feet
4000 feet
MAP TYPE
Standard
Satellite
Hybrid
I want to have one check mark for a row per section but my current code will uncheck all visible cells for the entire table view and leave one selected row with check mark. In other word, I will have one check mark for the entire table (2 sections). Here I posted my entire code. I have google'd many but there seems none to resolve my problem. Anyone, please help correct my code. Thanks in advance.
#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 2;
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.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.textLabel.text = [self maptypeLabelForCell:indexPath];
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.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.accessoryType = UITableViewCellAccessoryNone;
}
}
selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
PAWMaptypeSelect maptypeForCell = [self maptypeForCell:indexPath];
}
}
#end
you have an error with this
// uncheck all visible cells.
for (UITableViewCell *cell in [aTableView visibleCells]) {
if (cell.accessoryType != UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
Here the for loop deselect all the cell. you have to check also the section in if loop
you can set tag for your cell like this
cell.tag = indexPath.section;
and in for loop if condition is
for (UITableViewCell *cell in [aTableView visibleCells]) {
if (cell.accessoryType != UITableViewCellAccessoryNone && cell.tag == indexPath.section) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
problem in your code is that You only checkmark row for section 0 by replace below method you can solved your problem.
- (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.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.textLabel.text = [self maptypeLabelForCell:indexPath];
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 {
return nil;
}
}
For now I have found the following bugs
You don't save which cell is selected for map type.
The way how you checkmark your cell is incorrect.
In switch you don't have to use break after return statement
In case kPAWSettingsTableViewNumberOfSections: you should return kPAWSettingsTableViewNumberOfSections
First two defects causes many boilerplate code. I think you should store the NSIndexPath's for each section that is selected as additional #property. Instead of unchecking all and checking tapped, you can do in tableView:didSelectRowAtIndexPath::
Determine which one should be selected.
Store local old value of your selectedIndexPath.
Change selectedIndexPath proprty to new one.
Reload both rows.
Then you have to add in tableView:cellForRowAtIndexPath: the following code:
if (indexPath.row == self.selectedIndexPath.row && indexPath.section == self.selectedIndexPath.section) {
// Change to checkmark.
} else {
// Change to not checked.
}
I got very similar way to checkmark cell in my own project. I hope the code below also will help you understand my way to fix your problem:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (/*condition*/) {
[...]
}
else if (/*checkmark section*/) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CheckmarkCellId forIndexPath:indexPath];
cell.textLabel.text = [self labelForRow:indexPath.row];
cell.accessoryType = (indexPath.row == [self defaultAgglomerationIndex]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.imageView.image = (indexPath.row == [self selectedAgglomerationIndex]) ? [UIImage imageNamed:#"icoMap"] : [UIImage imageNamed:#"region"];
return cell;
}
else if (/*Another condition */) {
[...]
}
return nil;
}
And essencial code in tableView:didSelectRowAtIndexPath: (I reload whole section)
self.selectedIndex = indexPath;
NSIndexSet *set = [NSIndexSet indexSetWithIndex:indexPath.section];
[self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationNone];
Try this, worked just fine for me:
-VARIABLES:
#property NSInteger checkedCellRow;
#property NSInteger checkedCellSection;
-FUNCTIONS:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (checkedCellSection == indexPath.section)
{
if (checkedCellRow == indexPath.row)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
checkedCellRow = indexPath.row;
checkedCellSection = indexPath.section;
[myTable reloadData];
}
So I have a deadline coming up for this project and I've been working hard on it and so I'm pretty tired right now. I don't know if I'm just being stupid and blind to what I'm doing wrong but I have a problem that I need help with.
So, I'm trying to implement a sort of "expanding tableview setup" (like in IOS 7 calendar where you tap on the start and end dates and a cell pops in with a date picker). I have two different cells that can be displayed under a tapped cell. It works perfectly except for the actual cell, when I insert a row the wrong cell is displayed. I'll give some context... I have two cells in section 0, when you tap on the first cell it inserts a cell below it that should be a picker cell. Instead it inserts the same call as in row 1 of the unmodified tableview.
Here is the relevant code:
#interface AddMealTableViewController ()
#property (nonatomic) BOOL datePickerEnabled;
#property (nonatomic) BOOL pickerEnabled;
#property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
#property (nonatomic, strong) NSIndexPath *pickerIndexPath;
#end
#implementation AddMealTableViewController
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
switch (section) {
case 0:
return 2 + (self.datePickerEnabled) + (self.pickerEnabled);
break;
default:
return self.mealComponents.count;
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section) {
case 0:
{
if (indexPath.row == 1) {
TimeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TimeCell"];
cell.timeLabel.text = #"Now";
cell.mealTypeLabel.text = self.selectedMealType;
return cell;
}
else if (indexPath == self.datePickerIndexPath) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DateCell"];
return cell;
}
else if (indexPath == self.pickerIndexPath) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PickerCell"];
return cell;
}
else {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MealTypeCell"];
cell.textLabel.text = #"Meal Type";
cell.detailTextLabel.text = self.selectedMealType;
return cell;
}
break;
}
default:
{
ComponentCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ComponentCell"];
if (!cell) {
cell = [ComponentCell new];
}
MealComponent *mc = self.mealComponents[indexPath.row];
[cell setUpWithComponent:mc];
return cell;
break;
}
}
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
if (indexPath == self.datePickerIndexPath || indexPath == self.pickerIndexPath) {
return 200;
}
return self.tableView.rowHeight;
}
return 70;
}
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
if (self.datePickerEnabled)
{
self.datePickerEnabled = NO;
self.datePickerIndexPath = nil;
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
else
{
self.datePickerIndexPath = indexPaths.lastObject;
self.datePickerEnabled = YES;
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
- (void)togglePickerForSelectedIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
if (self.pickerEnabled)
{
self.pickerEnabled = NO;
self.pickerIndexPath = nil;
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
else
{
self.pickerIndexPath = indexPaths.lastObject;
self.pickerEnabled = YES;
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqual: #"TimeCell"]) {
[self toggleDatePickerForSelectedIndexPath:indexPath];
}
else if ([cell.reuseIdentifier isEqual: #"MealTypeCell"]) {
[self togglePickerForSelectedIndexPath:indexPath];
}
}
}
Any ideas? I really can't seem to put my finger on it.
why don't you change the height of date picker cell from 0 to 200 instead insert (or delete) the date picker cell. I think this is more simple.(This is what I'm used to implement that)
when [tableView didSelectRowAtIndexPath:] is called, you just call [tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic] to update cell.
You can managed the height of cell in [tableView heightForRowAtIndexPath:] you already know.
[edited]
I examine your code again.
change else if (indexPath == self.datePickefIndexPath) to else if([indexPath isEqual:self.datePickerIndexPath]) in [tableView:cellForRowAtIndexPath:]
There're many ways to handle this kind of things. You really don't need to insert or delete cell, just modify the cell height from 0 to the proper height. To do this, you can set a flag to check whether the cell's expanded or not.
I am working with the table view. I added the checkmark Accessory on the first tap of the screen and removed this checkmark on the second tap. I added few ckeckmarks on the cells of table view. Now i want that the labels of the cells having the checkmarks should be displayed on the NSlog.
please help me out regarding this issue. Any help will be much appriciable.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag == 0)
{
return [celltitles count];
}
else
{
return 7;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView.tag == 0)
{
cell.textLabel.text = [celltitles objectAtIndex:indexPath.row];
if (indexPath.row == 0)
{
habitname = [[UITextField alloc]initWithFrame:CGRectMake(150, 0, 150, 50)];
habitname.placeholder = #"Habit Name";
habitname.delegate= self;
[cell addSubview:habitname];
}
else if (indexPath.row == 1)
{
timelbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 220, 50)];
timelbl.text = #"OFF";
timelbl.textAlignment = NSTextAlignmentCenter;
[cell addSubview:timelbl];
timetitlelbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
timetitlelbl.text = #"Alert";
timetitlelbl.textAlignment = NSTextAlignmentCenter;
[cell addSubview:timetitlelbl];
toggleswitch = [[UISwitch alloc] initWithFrame:CGRectMake(250, 5, 50, 60)];
toggleswitch.on = NO;
[toggleswitch addTarget:self action:#selector(toggleSwitch) forControlEvents:(UIControlEventValueChanged | UIControlEventTouchDragInside)];
[cell addSubview:toggleswitch];
}
}
else if (tableView.tag == 1)
{
cell.textLabel.text = [daysarray objectAtIndex:indexPath.row];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1)
{
if (toggleswitch.on)
{
[self datepickershown:timelbl.text animated:YES];
if (self.datePickerIsShowing)
{
//[self datepickershown];
//[self hideDatePickerCell];
[dscptxt resignFirstResponder];
}
else
{
[dscptxt resignFirstResponder];
[self.timelbl resignFirstResponder];
[self showDatePickerCell];
}
}
else
{
timelbl.textColor = [UIColor grayColor];
}
}
else if (indexPath.row > 2 && indexPath.row <10)
{
NSLog(#"I am Selectin the row");
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
// NSLog(#"Selected Accessory Is %d",cell.accessoryType);
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
[self.tableview deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)savedata:(id)sender
{
}
Above is the code which i am using and on the save action i want the log.
Don't use the UITableView to store your data. Cells are reused, so that's not a reliable way to detect which items you have selected.
You could store whether an item is selected in an array, for instance. Then in your cellForRowAtIndexPath determine if the checkmark should be displayed. In didSelectRowAtIndexPath you update the model (your array) and request a reload for the specific cell.
This will result in a better MVC separation.
EDIT: added example for the UITableView stuff
// for this example we'll be storing NSIndexPath objects in our Model
// you might want to use a #property for this
NSMutableSet *model = [NSMutableSet set];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
if([model containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
...
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
// update the model
if([model containsObject:indexPath]) {
[model removeObject:indexPath];
}
else {
[model addObject:indexPath];
}
// request reload of selected cell
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation: UITableViewRowAnimationFade];
...
}
Now it should be fairly easy to log all selected items, without having to use the UITableView: it's all in your model now!
Make a for loop:
NSMutableArray *mutArray = [[NSMutableArray alloc] init];
for(i = 0;i <= self.rowCount-1;i++)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
[mutArray addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
}
NSLog(#"Array: %#", mutArray);