Reputation: 4882
I am building an app in Xcode 5, and I ran into some strange behavior of UISegmentedControl
.
first some info on the app i'm building:
I'm building an app in which I want to allow users to order products at registered companies. As an extra service, I want to allow them to see the orders they did, and even to filter the orders on their status: All orders, Active orders & Delivered orders. the orders are displayed in a UITableView, and I created a UISegmentedControl
inside the header view to filter the orders. when the selectedSegmentIndex
of that UISegmentedControl
changes, it executes an NSPredicate
to filter the array and display only the desired orders.
now it's working all fine, except for 1 thing: The UISegmentedControl
I have does not update it's view when I select another segment. It's default selectedSegmentIndex
is 'Active
', because users are probably most interested in the active orders, but when I change it to 'All', the tableview displays all orders (so the predicate is working), but the view remains on the same selectedSegmentIndex
.
I did a lot of research to solve this but no answer solves my problem.. my code:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(section == 0) {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f,0.0f, 320, 45)]; // x,y,width,height
//label
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320, 20)];
title.text = @"Kies een filter...";
[headerView addSubview:title];
//segmentedcontrol
NSArray *itemArray = [NSArray arrayWithObjects: @"Alle", @"Actief", @"Afgehandeld", nil];
control = [[UISegmentedControl alloc] initWithItems:itemArray];
[control setFrame:CGRectMake(0.0f, 20.0f, 320.0, 35.0)];
control.userInteractionEnabled = YES;
control.tintColor = [UIColor blackColor];
[control setEnabled:YES];
[control addTarget:self action:@selector(changeFilter:) forControlEvents:UIControlEventAllEvents];
[headerView addSubview:control];
//label containing selected filter info
UILabel *info = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 55.0f, 320, 20)];
if ([selectedFilterInfo isEqualToString:@"Alle"]) {
info.text = @"Alle orders:";
}
else if ([selectedFilterInfo isEqualToString:@"Actief"]) {
info.text = @"Alle actieve orders:";
}
else if ([selectedFilterInfo isEqualToString:@"Afgehandeld"]) {
info.text = @"Alle afgehandelde orders:";
}
[headerView addSubview:info];
headerView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bar.png"]];
return headerView;
}
}
and the action it triggers:
- (void)changeFilter:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
if (segmentedControl.selectedSegmentIndex == 0) {
selectedFilterInfo = @"Alle";
filteredArray = nil;
[segmentedControl reloadInputViews];
[segmentedControl setSelectedSegmentIndex:0];
}
else if (segmentedControl.selectedSegmentIndex == 1) {
NSPredicate *deliveredpredicate = [NSPredicate predicateWithFormat:@"SELF.delivered contains[c] %@", @"0"];
NSMutableArray *notDeliveredArray = [NSMutableArray arrayWithArray:[sortedArray filteredArrayUsingPredicate:deliveredpredicate]];
filteredArray = [NSMutableArray arrayWithArray:notDeliveredArray];
selectedFilterInfo = @"Actief";
[segmentedControl reloadInputViews];
[segmentedControl setSelectedSegmentIndex:1];
}
else if (segmentedControl.selectedSegmentIndex == 2) {
NSPredicate *deliveredpredicate = [NSPredicate predicateWithFormat:@"SELF.delivered contains[c] %@", @"1"];
NSArray *deliveredArray = [sortedArray filteredArrayUsingPredicate:deliveredpredicate];
filteredArray = [NSMutableArray arrayWithArray:deliveredArray];
selectedFilterInfo = @"Afgehandeld";
[segmentedControl reloadInputViews];
[segmentedControl setSelectedSegmentIndex:2];
}
[self.tableView reloadData];
}
I did not include the numberOfCellsInSection
etcetera because the tableview part is working perfectly. the only thing that's not working is updating the view.
Any solution would be really appreciated, Thank you all in advance!!
Upvotes: 3
Views: 2486
Reputation: 90117
reloadData will reload the tableView, and when you reload the tableView all headerViews will be reloaded too. When the tableView was reloaded there is a new header. And the UISegmentedControl you see now is not the one that you have tapped.
Create an ivar that holds your selected index
@implementation .. {
NSInteger selectedIndex;
}
when creating the view restore the saved index
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
/* ... */
control = [[UISegmentedControl alloc] initWithItems:itemArray];
control.selectedSegmentIndex = selectedIndex;
/* ... */
}
save the index when changing the segmentedControl
- (void)changeFilter:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
selectedIndex = segmentedControl.selectedSegmentIndex;
if (segmentedControl.selectedSegmentIndex == 0) {
selectedFilterInfo = @"Alle";
filteredArray = nil;
}
/* ... */
// reloads the table and all header views!
[tableView reloadData];
}
And btw. when you use UISegmentedControls there is no need to call setSelectedSegmentIndex:
on it again, the tap sets the index already. And reloadInputViews is totally useless for a UISegmentedControl. But I guess this code was just added because it didn't work. Don't forget to remove it ;-)
Upvotes: 7