I'm new to iOS. I'm using storyboard for UI development. I created a custom header cell with a label and activity Indicator. I created two section in my table view.In first section there is one row and in that row there is a switch in the accessory view.Now is want to do when I on/off the switch the activity indicator start/stop animating.But this is not happening in my case. please help me.
Here is the code snippet:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"bluetoothCell"];
UISwitch *addswitch=nil;
if (addswitch==nil)
{
addswitch=[[UISwitch alloc]initWithFrame:(CGRectZero)];
}
if (indexPath.section==0)
{
if (indexPath.row==0)
{
cell.accessoryView=addswitch;
[addswitch addTarget:self action:#selector(bluetoohSwitchClicked:) forControlEvents:UIControlEventValueChanged ];
cell.textLabel.text=#"Bluetooth";
}
}
else if (indexPath.section==1) {
cell.textLabel.text=#"bluetooth devices";
cell.accessoryView=nil;
}
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 44.0;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection: (NSInteger)section
{
HeaderTableViewCell *customheader;
NSLog(#"section.. %ld",(long)section);
customheader=[ tableView dequeueReusableCellWithIdentifier:#"headercell"];
self.customheader=customheader;
customheader.autoresizesSubviews=YES;
if (section==0) {
customheader.activityloader2.hidden=NO;
customheader.tag=0;
NSLog(#"section %ld,%#",(long)section,customheader);
}
else if(section==1) {
customheader.activityloader2.hidden=NO;
customheader.tag=1;
NSLog(#"sections %ld,%#",(long)section,customheader);
}
return customheader;
}
-(void)bluetoohSwitchClicked:(id) sender
{
UISwitch* switchControl = sender;
if ([switchControl isOn])
{
self.onoffswitch=#"ON";
[switchControl setOn:YES animated:YES];
}
else
{
self.onoffswitch=#"OFF";
[switchControl setOn:NO animated:YES];
}
[self bluetoothStatechanged:[self.onoffswitch isEqualToString:#"ON"]? YES:NO];
}
-(void)bluetoothStatechanged:(BOOL)on
{
HeaderTableViewCell* customheader=(HeaderTableViewCell *)[self tableView:self.maintableview2 viewForHeaderInSection:1];
__block CGRect frame=customheader.frame;
if (on==YES) {
[customheader.activityloader2 startAnimating];
NSLog(#"yes block");
}
else
{
[customheader.activityloader2 stopAnimating];
NSLog(#"No block");
}
}
Related
I am getting JSONArray data and show phone numbers in table
I am using UISearchBar in UITableView.
When I am type in search bar it reload data and show type value in first cell.
But i clicked first cell means it show old array value.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (isSearching)
{
cell.textLabel.text = [searchResultArray objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [phoneNoArray objectAtIndex:indexPath.row];
}
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[searchResultArray removeAllObjects];
if([searchText length] != 0)
{
isSearching = YES;
[self searchTableList];
}
else
{
isSearching = NO;
}
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
tempString = [jsonArray objectAtIndex:indexPath.row];
}
when you set isSearching to yes. Now datasoucre of table has changed. and you have reloaded the data.
and you are supposed to update your datasource methods as well
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isSearching) {
return [searchResultArray count];
}
else
{
return [phoneNoArray count];
}
}
HTH
I have created a stepper in a CustomCell of a UITableView. However, I would like the stepper to only be visible when a particular row is selected. To this end, I tried the following:
In tableView:cellForRowAtIndexPath:
cell.customStepper.hidden=NO;
and in tableView:didSelectRowAtIndexPath:
cell.customStepper.hidden=YES;
But the stepper is still hidden. What am I missing?
#interface BRNCategoryViewController ()
{
NSMutableArray *arySelectCategory;
NSMutableArray *aryCategory;
}
- (void) viewDidLoad
{
arySelectCategory=[NSMutableArray new];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return aryCategory.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BRNCategoryCell *cell=[[BRNCategoryCell alloc]initWithOwner:self];
if ([arySelectCategory containsObject:[aryCategory objectAtIndex:indexPath.row]])
{
cell.customStepper.hidden = NO;
}
else
{
cell.customStepper.hidden = YES;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([arySelectCategory containsObject:[aryCategory objectAtIndex:indexPath.row]])
{
[arySelectCategory removeObject:[aryCategory objectAtIndex:indexPath.row]];
}
else
{
[arySelectCategory addObject:[aryCategory objectAtIndex:indexPath.row]];
}
[tblEventCategory reloadData];
}
In cellForRowAtIndexPath
cell.customStepper.hidden=YES;
And
In didSelectRowAtIndexPath
VideosCell *cell = (VideosCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.customStepper.hidden = NO;
When you click on a cell inside a TableView, it will expand.
How I achieved this was with the following methods:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.topicsArray containsObject:indexPath])
{
[self.topicsArray removeObject:indexPath];
}
else
{
[_topicsArray addObject:indexPath];
}
[_tableView beginUpdates];
[_tableView endUpdates];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat kExpandedCellHeight = 240;
CGFloat kNormalCellHeigh = 115;
if ([_topicsArray containsObject:indexPath])
{
return kExpandedCellHeight;
}
else
{
return kNormalCellHeigh;
}
}
What I cannot figure out how to do is - How to 'shrink' all the cells in a TableView before I expand the one clicked on?!
aha i got it you dont remove the index from the array. try [topicsArray removeAllObjects] before
if ([self.topicsArray containsObject:indexPath])
{
[self.topicsArray removeObject:indexPath];
}
else
{
[_topicsArray addObject:indexPath];
}
I have a UITableView in which I need to programmatically select a cell if the data model says that the cell represents the selected choice in a list of items. I do this when I'm configuring the UITableViewCell:
if (group == self.theCase.assignedGroup) {
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
self.selectedIndexPath = indexPath;
} else {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I am seeing very odd behavior with this. If the first row of the tableview is the one that should be selected, the cell doesn't highlight its background properly. However, if the second row is the one that should be selected, it works as it's supposed to (screenshots at the end).
UPDATE: It could have something to do with the fact that I am loading data for the table asynchronously, and while the data is loading I show a different kind of cell with a progress indicator in that first row. Here's the table view data source code that's handling this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if (self.hasMorePages) {
return self.groups.count + 1;
}
return self.groups.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if (indexPath.row < self.groups.count) {
cell = [tableView dequeueReusableCellWithIdentifier:#"DSAssignCell" forIndexPath:indexPath];
[self configureCell:cell forRowAtIndexPath:indexPath];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"DSLoadingCell" forIndexPath:indexPath];
[self configureLoadingCell:cell forRowAtIndexPath:indexPath];
}
return cell;
}
- (void)configureCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
DSGroup *group = self.groups[indexPath.row];
if (group == self.theCase.assignedGroup) {
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
self.selectedIndexPath = indexPath;
} else {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
cell.textLabel.text = group.name;
cell.tag = kDataCellTag;
}
- (void)configureLoadingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIActivityIndicatorView *activityIndicator;
if ([cell viewWithTag:kActivityIndicatorTag]) {
activityIndicator = (UIActivityIndicatorView *)[cell viewWithTag:kActivityIndicatorTag];
} else {
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = cell.center;
activityIndicator.tag = kActivityIndicatorTag;
[cell.contentView addSubview:activityIndicator];
}
[activityIndicator startAnimating];
cell.tag = kLoadingCellTag;
}
UPDATE As requested, here is the code that handles the asynchronous loading of the group & agent data from the web service:
- (void)viewDidLoad
{
[super viewDidLoad];
[self resetData];
[self loadData];
}
- (void)resetData
{
self.currentPage = 0;
self.hasMorePages = YES;
self.groups = [[NSMutableArray alloc] initWithCapacity:kGroupsPerPage];
self.agents = [[NSMutableArray alloc] initWithCapacity:kAgentsPerPage];
}
- (void)loadData
{
if (self.showingGroups) {
[DSGroup fetchGroupsOnPage:self.currentPage + 1 perPage:kGroupsPerPage success:^(NSArray *groups, NSDictionary *links, NSNumber *totalEntries) {
[self.groups addObjectsFromArray:groups];
[self didLoadDataPage:(links[#"next"] != [NSNull null])];
} failure:^(NSError *error) {
[self showAlert:#"Could not load groups. Please try again later." withError:error];
}];
} else {
[DSUser fetchUsersOnPage:self.currentPage + 1 perPage:kAgentsPerPage success:^(NSArray *users, NSDictionary *links, NSNumber *totalEntries) {
[self.agents addObjectsFromArray:users];
[self didLoadDataPage:(links[#"next"] != [NSNull null])];
} failure:^(NSError *error) {
[self showAlert:#"Could not load users. Please try again later." withError:error];
}];
}
}
- (void)didLoadDataPage:(BOOL)hasMorePages
{
self.hasMorePages = hasMorePages;
self.currentPage++;
[self.tableView reloadData];
}
Here's a screenshot of trying to select (and highlight) the first row, which is wrong (no gray background):
Here's a screenshot of trying to select (and highlight) the second row, which is correct:
Any idea what might be going on here?
I wasn't able to fix this using the built-in selection styles of UITableViewCell, but subclassing it and overriding setSelected:animated fixed it:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
self.contentView.backgroundColor = selected ? [UIColor grayColor] : [UIColor whiteColor];
}
I have a UITableViewController that toggles into its editing mode when the user presses a button in the toolbar. I want the user to select multiple cells and then put a rounded red checkmark on the left side of each selected cell. I've selected Multiple Selection During Editing in the table view in Storyboard and no accessory / editing accessory for my custom cell.
The problem is that I can find each tapped cell in the tableView's indexPathsForSelectedRows, but the red checkmark on the left of each selected cell doesn't appear. However, after leaving editing mode, each selected cell shows a checkmark accessory on the right (which I don't need anymore after finishing editing).
While editing:
After editing:
Here is what I did in code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.editing)
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone)
{
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
}
}
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if (tableView.editing)
{
cell.accessoryType = UITableViewCellAccessoryNone;
for (NSIndexPath *selectedIndex in [self.tableView indexPathsForSelectedRows])
{
if ([selectedIndex isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
}
}
...
Thanks!
If anyone comes across the same issue, here is a snipped of how I've solved it. I have a toolbar button connected to an IBAction that toggles the UITableView's editing mode. When editing is enabled, the user can select rows and hit a delete button which has the number of selected rows set in its label.
#interface TableViewController ()
{
NSMutableArray *selectedCellRows; // Used to remember which cells have been selected during editing mode
}
- (IBAction)toggleEditing:(id)sender;
#end
#implementation TableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GeneralReservationCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CELL_IDENTIFIER];
// Set up the cell...
[self configureCell:cell forTableView:tableView atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(GeneralReservationCell *)cell forTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{
// Basic layout
cell.nameLabel.text = #"Some text";
cell.selected = NO;
if (tableView.editing)
{
for (NSIndexPath *selectedIndex in selectedCellRows)
{
if ([selectedIndex isEqual:indexPath])
{
cell.selected = YES;
break;
}
}
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.editing)
{
[selectedCellRows addObject:indexPath];
[self updateEditingToolbarButton];
}
else
{
// Do whatever you do normally when the cell gets selected
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.editing)
{
[selectedCellRows removeObject:indexPath];
[self updateEditingToolbarButton];
}
}
- (void)updateEditingToolbarButton
{
int selectedRows = [self.tableView.indexPathsForSelectedRows count];
if (selectedRows == 0)
{
[deleteBarButton setTitle:#"delete"];
deleteBarButton.enabled = NO;
}
else
{
[deleteBarButton setTitle:[NSString stringWithFormat:#"delete (%d)", selectedRows]];
deleteBarButton.enabled = YES;
}
}
#pragma mark - IBActions
- (IBAction)toggleEditing:(id)sender
{
if(self.tableView.editing)
{
[self.tableView setEditing:NO animated:YES];
[selectedCellRows removeAllObjects];
[self showToolbarInEditingMode:NO];
}
else
{
[self.tableView setEditing:YES animated:YES];
[self showToolbarInEditingMode:YES];
}
}
#end
Additionally, I set the Editing Accessory to none in Interface Builder.
If you want the rounded circle to be filled when the cell is checked, you need to set the cell's selectionStyle to other than none.
cell.selectionStyle = .blue
This can also be set in the interface builder.
Also you if you don't want the checkmark when not editing the tableView, you need to set the cell's accessoryType to .none in your else block.
if tableView.isEditing {
...
} else {
cell.accessoryType = .none
}